Mir

Merge lp:~robertcarr/mir/enable-pointer-touch-input into lp:~mir-team/mir/trunk

Proposed by Robert Carr
Status: Superseded
Proposed branch: lp:~robertcarr/mir/enable-pointer-touch-input
Merge into: lp:~mir-team/mir/trunk
Prerequisite: lp:~robertcarr/mir/reflow-input-focus-selection
Diff against target: 2660 lines (+1016/-387)
50 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/input/surface_target.h (+2/-0)
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/server/mir/shell/surface.h (+1/-0)
include/test/mir_test/event_matchers.h (+64/-0)
include/test/mir_test/fake_event_hub_input_configuration.h (+2/-0)
include/test/mir_test_doubles/mock_event_filter.h (+0/-32)
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_doubles/stub_surface_target.h (+4/-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/android_input_reader_policy.cpp (+3/-0)
src/server/input/android/android_input_window_handle.cpp (+8/-2)
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 (+6/-5)
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)
src/server/shell/surface.cpp (+12/-0)
tests/acceptance-tests/test_client_input.cpp (+145/-35)
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 (+71/-12)
tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp (+2/-1)
tests/integration-tests/shell/test_session_manager.cpp (+24/-17)
tests/mir_test_doubles/fake_event_hub.cpp (+2/-2)
tests/mir_test_framework/testing_server_options.cpp (+3/-11)
tests/unit-tests/input/android/test_android_dispatcher_controller.cpp (+138/-13)
tests/unit-tests/input/android/test_android_input_window_handle.cpp (+11/-0)
tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp (+15/-2)
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 (+72/-8)
tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp (+1/-24)
tests/unit-tests/shell/test_surface.cpp (+18/-0)
tests/unit-tests/shell/test_the_session_container_implementation.cpp (+7/-4)
To merge this branch: bzr merge lp:~robertcarr/mir/enable-pointer-touch-input
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Information
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+160153@code.launchpad.net

This proposal supersedes a proposal from 2013-04-22.

This proposal has been superseded by a proposal from 2013-04-23.

Commit message

Enable motion and touch/button events

Description of the change

Enable motion events in the DispatcherPolicy and Window Handle. This branch is largely new acceptance tests! (small changes to event_filter_dispatcher_policy and android_input_window_handle).

Depends on:
~robertcarr/mir/reflow-input-focus-selection

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:605
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~robertcarr/mir/enable-pointer-touch-input/+merge/160153/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/468/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-raring-i386-build/498
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-raring-amd64-build/381
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-quantal-amd64-ci/473/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/mir-ci/468/rebuild

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
Daniel van Vugt (vanvugt) wrote :

1744 +TEST_F(AndroidInputManagerDispatcherInterceptSetup, changing_focus_changes_event_recipient)

It's not the test that needs fixing, but the fundamental assumption behind it. Touch and pointer events are never affected by focus. Focus only relates to key events, because key events lack an (x,y).

Because touch and pointer events already have (x,y) they do not relate to focus. Please remove this assumption if it has been made... ?

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

Looks mostly sensible. I'm not convinced by the name "InputTargetListener" as what it "listens" to are session and surface lifecycle messages, not input target messages.

I'll comment further after a closer look.

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 21:32:25 +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 21:32:25 +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 21:32:25 +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 21:32:25 +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/input/surface_target.h'
132--- include/server/mir/input/surface_target.h 2013-04-16 09:08:29 +0000
133+++ include/server/mir/input/surface_target.h 2013-04-22 21:32:25 +0000
134@@ -20,6 +20,7 @@
135 #define MIR_INPUT_SURFACE_TARGET_H_
136
137 #include "mir/geometry/size.h"
138+#include "mir/geometry/point.h"
139
140 #include <string>
141
142@@ -33,6 +34,7 @@
143 public:
144 virtual ~SurfaceTarget() {}
145
146+ virtual geometry::Point top_left() const = 0;
147 virtual geometry::Size size() const = 0;
148 virtual std::string name() const = 0;
149
150
151=== modified file 'include/server/mir/shell/application_session.h'
152--- include/server/mir/shell/application_session.h 2013-04-16 17:42:26 +0000
153+++ include/server/mir/shell/application_session.h 2013-04-22 21:32:25 +0000
154@@ -30,11 +30,13 @@
155 {
156 class SurfaceFactory;
157 class Surface;
158+class InputTargetListener;
159
160 class ApplicationSession : public Session
161 {
162 public:
163- explicit ApplicationSession(std::shared_ptr<SurfaceFactory> const& surface_factory, std::string const& session_name);
164+ explicit ApplicationSession(std::shared_ptr<SurfaceFactory> const& surface_factory,
165+ std::shared_ptr<InputTargetListener> const& input_target_listener, std::string const& session_name);
166 ~ApplicationSession();
167
168 frontend::SurfaceId create_surface(frontend::SurfaceCreationParameters const& params);
169@@ -58,6 +60,7 @@
170
171 private:
172 std::shared_ptr<SurfaceFactory> const surface_factory;
173+ std::shared_ptr<InputTargetListener> const input_target_listener;
174 std::string const session_name;
175
176 frontend::SurfaceId next_id();
177
178=== removed file 'include/server/mir/shell/input_focus_selector.h'
179--- include/server/mir/shell/input_focus_selector.h 2013-04-16 09:08:29 +0000
180+++ include/server/mir/shell/input_focus_selector.h 1970-01-01 00:00:00 +0000
181@@ -1,52 +0,0 @@
182-/*
183- * Copyright © 2013 Canonical Ltd.
184- *
185- * This program is free software: you can redistribute it and/or modify it
186- * under the terms of the GNU General Public License version 3,
187- * as published by the Free Software Foundation.
188- *
189- * This program is distributed in the hope that it will be useful,
190- * but WITHOUT ANY WARRANTY; without even the implied warranty of
191- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
192- * GNU General Public License for more details.
193- *
194- * You should have received a copy of the GNU General Public License
195- * along with this program. If not, see <http://www.gnu.org/licenses/>.
196- *
197- * Authored by: Robert Carr <robert.carr@canonical.com>
198- */
199-
200-#ifndef MIR_SHELL_INPUT_FOCUS_SELECTOR_H_
201-#define MIR_SHELL_INPUT_FOCUS_SELECTOR_H_
202-
203-#include <memory>
204-
205-namespace mir
206-{
207-namespace input
208-{
209-class SessionTarget;
210-class SurfaceTarget;
211-}
212-
213-namespace shell
214-{
215-
216-class InputFocusSelector
217-{
218-public:
219- virtual ~InputFocusSelector() {}
220-
221- virtual void set_input_focus_to(std::shared_ptr<input::SessionTarget> const& focus_application,
222- std::shared_ptr<input::SurfaceTarget> const& focus_surface) = 0;
223-
224-protected:
225- InputFocusSelector() = default;
226- InputFocusSelector(InputFocusSelector const&) = delete;
227- InputFocusSelector& operator=(InputFocusSelector const&) = delete;
228-};
229-
230-}
231-} // namespace mir
232-
233-#endif // MIR_SHELL_INPUT_FOCUS_SELECTOR_H_
234
235=== added file 'include/server/mir/shell/input_target_listener.h'
236--- include/server/mir/shell/input_target_listener.h 1970-01-01 00:00:00 +0000
237+++ include/server/mir/shell/input_target_listener.h 2013-04-22 21:32:25 +0000
238@@ -0,0 +1,59 @@
239+/*
240+ * Copyright © 2013 Canonical Ltd.
241+ *
242+ * This program is free software: you can redistribute it and/or modify it
243+ * under the terms of the GNU General Public License version 3,
244+ * as published by the Free Software Foundation.
245+ *
246+ * This program is distributed in the hope that it will be useful,
247+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
248+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
249+ * GNU General Public License for more details.
250+ *
251+ * You should have received a copy of the GNU General Public License
252+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
253+ *
254+ * Authored by: Robert Carr <robert.carr@canonical.com>
255+ */
256+
257+#ifndef MIR_SHELL_INPUT_TARGET_LISTENER_H_
258+#define MIR_SHELL_INPUT_TARGET_LISTENER_H_
259+
260+#include <memory>
261+
262+namespace mir
263+{
264+namespace input
265+{
266+class SessionTarget;
267+class SurfaceTarget;
268+}
269+
270+namespace shell
271+{
272+
273+class InputTargetListener
274+{
275+public:
276+ virtual ~InputTargetListener() = default;
277+
278+ virtual void input_application_opened(std::shared_ptr<input::SessionTarget> const& application) = 0;
279+ virtual void input_application_closed(std::shared_ptr<input::SessionTarget> const& application) = 0;
280+
281+ virtual void input_surface_opened(std::shared_ptr<input::SessionTarget> const& application,
282+ std::shared_ptr<input::SurfaceTarget> const& opened_surface) = 0;
283+ virtual void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface) = 0;
284+
285+ virtual void focus_changed(std::shared_ptr<input::SurfaceTarget> const& focus_surface) = 0;
286+ virtual void focus_cleared() = 0;
287+
288+protected:
289+ InputTargetListener() = default;
290+ InputTargetListener(InputTargetListener const&) = delete;
291+ InputTargetListener& operator=(InputTargetListener const&) = delete;
292+};
293+
294+}
295+} // namespace mir
296+
297+#endif // MIR_SHELL_INPUT_TARGET_LISTENER_H_
298
299=== modified file 'include/server/mir/shell/session_manager.h'
300--- include/server/mir/shell/session_manager.h 2013-04-19 09:15:31 +0000
301+++ include/server/mir/shell/session_manager.h 2013-04-22 21:32:25 +0000
302@@ -40,15 +40,17 @@
303 class SessionContainer;
304 class FocusSequence;
305 class FocusSetter;
306+class InputTargetListener;
307 class Session;
308
309 class SessionManager : public frontend::Shell
310 {
311 public:
312 explicit SessionManager(std::shared_ptr<SurfaceFactory> const& surface_factory,
313- std::shared_ptr<SessionContainer> const& session_container,
314+ std::shared_ptr<SessionContainer> const& app_container,
315 std::shared_ptr<FocusSequence> const& focus_sequence,
316- std::shared_ptr<FocusSetter> const& focus_setter);
317+ std::shared_ptr<FocusSetter> const& focus_setter,
318+ std::shared_ptr<InputTargetListener> const& input_target_listener);
319 virtual ~SessionManager();
320
321 virtual std::shared_ptr<frontend::Session> open_session(std::string const& name);
322@@ -71,6 +73,7 @@
323 std::shared_ptr<SessionContainer> const app_container;
324 std::shared_ptr<FocusSequence> const focus_sequence;
325 std::shared_ptr<FocusSetter> const focus_setter;
326+ std::shared_ptr<InputTargetListener> const input_target_listener;
327
328 std::mutex mutex;
329 std::weak_ptr<Session> focus_application;
330
331=== modified file 'include/server/mir/shell/single_visibility_focus_mechanism.h'
332--- include/server/mir/shell/single_visibility_focus_mechanism.h 2013-04-16 09:08:29 +0000
333+++ include/server/mir/shell/single_visibility_focus_mechanism.h 2013-04-22 21:32:25 +0000
334@@ -28,13 +28,11 @@
335 namespace shell
336 {
337 class SessionContainer;
338-class InputFocusSelector;
339
340 class SingleVisibilityFocusMechanism : public FocusSetter
341 {
342 public:
343- explicit SingleVisibilityFocusMechanism(std::shared_ptr<SessionContainer> const& app_container,
344- std::shared_ptr<shell::InputFocusSelector> const& input_selector);
345+ explicit SingleVisibilityFocusMechanism(std::shared_ptr<SessionContainer> const& app_container);
346 virtual ~SingleVisibilityFocusMechanism() {}
347
348 void set_focus_to(std::shared_ptr<shell::Session> const& new_focus);
349@@ -44,7 +42,6 @@
350 SingleVisibilityFocusMechanism& operator=(const SingleVisibilityFocusMechanism&) = delete;
351 private:
352 std::shared_ptr<SessionContainer> const app_container;
353- std::shared_ptr<shell::InputFocusSelector> const input_selector;
354 };
355
356 }
357
358=== modified file 'include/server/mir/shell/surface.h'
359--- include/server/mir/shell/surface.h 2013-04-16 17:42:26 +0000
360+++ include/server/mir/shell/surface.h 2013-04-22 21:32:25 +0000
361@@ -63,6 +63,7 @@
362 virtual std::string name() const;
363
364 virtual geometry::Size size() const;
365+ virtual geometry::Point top_left() const;
366
367 virtual geometry::PixelFormat pixel_format() const;
368
369
370=== added file 'include/test/mir_test/event_matchers.h'
371--- include/test/mir_test/event_matchers.h 1970-01-01 00:00:00 +0000
372+++ include/test/mir_test/event_matchers.h 2013-04-22 21:32:25 +0000
373@@ -0,0 +1,64 @@
374+/*
375+ * Copyright © 2013 Canonical Ltd.
376+ *
377+ * This program is free software: you can redistribute it and/or modify it
378+ * under the terms of the GNU General Public License version 3,
379+ * as published by the Free Software Foundation.
380+ *
381+ * This program is distributed in the hope that it will be useful,
382+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
383+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
384+ * GNU General Public License for more details.
385+ *
386+ * You should have received a copy of the GNU General Public License
387+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
388+ *
389+ * Authored by: Robert Carr <robert.carr@canonical.com>
390+ */
391+
392+#ifndef MIR_TEST_EVENT_MATCHERS_H_
393+#define MIR_TEST_EVENT_MATCHERS_H_
394+
395+#include <androidfw/Input.h>
396+
397+#include <gmock/gmock.h>
398+
399+namespace mir
400+{
401+namespace test
402+{
403+
404+MATCHER_P(IsKeyEventWithKey, key, "")
405+{
406+ if (arg.type != mir_event_type_key)
407+ return false;
408+
409+ return arg.key.key_code == key;
410+}
411+MATCHER(KeyDownEvent, "")
412+{
413+ if (arg.type != mir_event_type_key)
414+ return false;
415+
416+ return arg.key.action == AKEY_EVENT_ACTION_DOWN;
417+}
418+MATCHER(ButtonDownEvent, "")
419+{
420+ if (arg.type != mir_event_type_motion)
421+ return false;
422+ if (arg.motion.button_state == 0)
423+ return false;
424+ return arg.motion.action == AMOTION_EVENT_ACTION_DOWN;
425+}
426+MATCHER_P2(MotionEvent, dx, dy, "")
427+{
428+ if (arg.type != mir_event_type_motion)
429+ return false;
430+ auto coords = &arg.motion.pointer_coordinates[0];
431+ return (coords->x == dx) && (coords->y == dy);
432+}
433+
434+}
435+} // namespace mir
436+
437+#endif // MIR_TEST_EVENT_MATCHERS_H_
438
439=== modified file 'include/test/mir_test/fake_event_hub_input_configuration.h'
440--- include/test/mir_test/fake_event_hub_input_configuration.h 2013-04-16 09:08:29 +0000
441+++ include/test/mir_test/fake_event_hub_input_configuration.h 2013-04-22 21:32:25 +0000
442@@ -63,6 +63,8 @@
443
444 droidinput::sp<droidinput::EventHubInterface> the_event_hub();
445 input::android::FakeEventHub* the_fake_event_hub();
446+
447+ bool is_key_repeat_enabled() override { return false; }
448
449
450 protected:
451
452=== modified file 'include/test/mir_test_doubles/mock_event_filter.h'
453--- include/test/mir_test_doubles/mock_event_filter.h 2013-04-16 09:08:29 +0000
454+++ include/test/mir_test_doubles/mock_event_filter.h 2013-04-22 21:32:25 +0000
455@@ -21,8 +21,6 @@
456
457 #include "mir/input/event_filter.h"
458
459-#include <androidfw/Input.h>
460-
461 #include <gmock/gmock.h>
462
463 namespace mir
464@@ -36,36 +34,6 @@
465 MOCK_METHOD1(handles, bool(const MirEvent&));
466 };
467 }
468-
469-MATCHER_P(IsKeyEventWithKey, key, "")
470-{
471- if (arg.type != mir_event_type_key)
472- return false;
473-
474- return arg.key.key_code == key;
475-}
476-MATCHER(KeyDownEvent, "")
477-{
478- if (arg.type != mir_event_type_key)
479- return false;
480-
481- return arg.key.action == AKEY_EVENT_ACTION_DOWN;
482-}
483-MATCHER(ButtonDownEvent, "")
484-{
485- if (arg.type != mir_event_type_motion)
486- return false;
487- if (arg.motion.button_state == 0)
488- return false;
489- return arg.motion.action == AKEY_EVENT_ACTION_DOWN;
490-}
491-MATCHER_P2(MotionEvent, dx, dy, "")
492-{
493- if (arg.type != mir_event_type_motion)
494- return false;
495- auto coords = &arg.motion.pointer_coordinates[0];
496- return (coords->x == dx) && (coords->y == dy);
497-}
498 }
499 }
500
501
502=== removed file 'include/test/mir_test_doubles/mock_input_focus_selector.h'
503--- include/test/mir_test_doubles/mock_input_focus_selector.h 2013-04-16 09:08:29 +0000
504+++ include/test/mir_test_doubles/mock_input_focus_selector.h 1970-01-01 00:00:00 +0000
505@@ -1,40 +0,0 @@
506-/*
507- * Copyright © 2013 Canonical Ltd.
508- *
509- * This program is free software: you can redistribute it and/or modify it
510- * under the terms of the GNU General Public License version 3,
511- * as published by the Free Software Foundation.
512- *
513- * This program is distributed in the hope that it will be useful,
514- * but WITHOUT ANY WARRANTY; without even the implied warranty of
515- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
516- * GNU General Public License for more details.
517- *
518- * You should have received a copy of the GNU General Public License
519- * along with this program. If not, see <http://www.gnu.org/licenses/>.
520- *
521- * Authored by: Robert Carr <robert.carr@canonical.com>
522- */
523-
524-#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_FOCUS_SELECTOR_H_
525-#define MIR_TEST_DOUBLES_MOCK_INPUT_FOCUS_SELECTOR_H_
526-
527-#include "mir/shell/input_focus_selector.h"
528-
529-namespace mir
530-{
531-namespace test
532-{
533-namespace doubles
534-{
535-
536-struct MockInputFocusSelector : public shell::InputFocusSelector
537-{
538- MOCK_METHOD2(set_input_focus_to, void(std::shared_ptr<input::SessionTarget> const&, std::shared_ptr<input::SurfaceTarget> const&));
539-};
540-
541-}
542-}
543-} // namespace mir
544-
545-#endif // MIR_TEST_DOUBLES_MOCK_INPUT_FOCUS_SELECTOR_H_
546
547=== added file 'include/test/mir_test_doubles/mock_input_target_listener.h'
548--- include/test/mir_test_doubles/mock_input_target_listener.h 1970-01-01 00:00:00 +0000
549+++ include/test/mir_test_doubles/mock_input_target_listener.h 2013-04-22 21:32:25 +0000
550@@ -0,0 +1,49 @@
551+/*
552+ * Copyright © 2013 Canonical Ltd.
553+ *
554+ * This program is free software: you can redistribute it and/or modify it
555+ * under the terms of the GNU General Public License version 3,
556+ * as published by the Free Software Foundation.
557+ *
558+ * This program is distributed in the hope that it will be useful,
559+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
560+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
561+ * GNU General Public License for more details.
562+ *
563+ * You should have received a copy of the GNU General Public License
564+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
565+ *
566+ * Authored by: Robert Carr <robert.carr@canonical.com>
567+ */
568+
569+#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
570+#define MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
571+
572+#include "mir/shell/input_target_listener.h"
573+
574+#include <gmock/gmock.h>
575+
576+namespace mir
577+{
578+namespace test
579+{
580+namespace doubles
581+{
582+
583+struct MockInputTargetListener : public shell::InputTargetListener
584+{
585+ virtual ~MockInputTargetListener() noexcept(true) {}
586+ MOCK_METHOD1(input_application_opened, void(std::shared_ptr<input::SessionTarget> const& application));
587+ MOCK_METHOD1(input_application_closed, void(std::shared_ptr<input::SessionTarget> const& application));
588+ MOCK_METHOD2(input_surface_opened, void(std::shared_ptr<input::SessionTarget> const& application,
589+ std::shared_ptr<input::SurfaceTarget> const& opened_surface));
590+ MOCK_METHOD1(input_surface_closed, void(std::shared_ptr<input::SurfaceTarget> const& closed_surface));
591+ MOCK_METHOD1(focus_changed, void(std::shared_ptr<input::SurfaceTarget> const& focus_surface));
592+ MOCK_METHOD0(focus_cleared, void());
593+};
594+
595+}
596+}
597+} // namespace mir
598+
599+#endif // MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
600
601=== added file 'include/test/mir_test_doubles/stub_input_target_listener.h'
602--- include/test/mir_test_doubles/stub_input_target_listener.h 1970-01-01 00:00:00 +0000
603+++ include/test/mir_test_doubles/stub_input_target_listener.h 2013-04-22 21:32:25 +0000
604@@ -0,0 +1,59 @@
605+/*
606+ * Copyright © 2013 Canonical Ltd.
607+ *
608+ * This program is free software: you can redistribute it and/or modify it
609+ * under the terms of the GNU General Public License version 3,
610+ * as published by the Free Software Foundation.
611+ *
612+ * This program is distributed in the hope that it will be useful,
613+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
614+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
615+ * GNU General Public License for more details.
616+ *
617+ * You should have received a copy of the GNU General Public License
618+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
619+ *
620+ * Authored by: Robert Carr <robert.carr@canonical.com>
621+ */
622+
623+#ifndef MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
624+#define MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
625+
626+#include "mir/shell/input_target_listener.h"
627+
628+namespace mir
629+{
630+namespace test
631+{
632+namespace doubles
633+{
634+
635+struct StubInputTargetListener : public shell::InputTargetListener
636+{
637+ void input_application_opened(std::shared_ptr<input::SessionTarget> const&)
638+ {
639+ }
640+ void input_application_closed(std::shared_ptr<input::SessionTarget> const&)
641+ {
642+ }
643+ void input_surface_opened(std::shared_ptr<input::SessionTarget> const&,
644+ std::shared_ptr<input::SurfaceTarget> const&)
645+ {
646+ }
647+ void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const&)
648+ {
649+ }
650+ void focus_changed(std::shared_ptr<input::SurfaceTarget> const&)
651+ {
652+ }
653+
654+ void focus_cleared()
655+ {
656+ }
657+};
658+
659+}
660+}
661+} // namespace mir
662+
663+#endif // MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
664
665=== modified file 'include/test/mir_test_doubles/stub_surface_target.h'
666--- include/test/mir_test_doubles/stub_surface_target.h 2013-04-16 09:08:29 +0000
667+++ include/test/mir_test_doubles/stub_surface_target.h 2013-04-22 21:32:25 +0000
668@@ -43,6 +43,10 @@
669 {
670 return geometry::Size();
671 }
672+ geometry::Point top_left() const override
673+ {
674+ return geometry::Point();
675+ }
676 std::string name() const override
677 {
678 return std::string();
679
680=== modified file 'include/test/mir_test_framework/testing_server_configuration.h'
681--- include/test/mir_test_framework/testing_server_configuration.h 2013-04-16 09:08:29 +0000
682+++ include/test/mir_test_framework/testing_server_configuration.h 2013-04-22 21:32:25 +0000
683@@ -49,7 +49,7 @@
684 // to avoid starting and stopping the full android input stack for tests
685 // which do not leverage input.
686 std::shared_ptr<input::InputManager> the_input_manager();
687- std::shared_ptr<shell::InputFocusSelector> the_input_focus_selector();
688+ std::shared_ptr<shell::InputTargetListener> the_input_target_listener();
689
690 virtual std::string the_socket_file() const;
691 using DefaultServerConfiguration::the_options;
692
693=== modified file 'src/server/default_server_configuration.cpp'
694--- src/server/default_server_configuration.cpp 2013-04-19 12:49:42 +0000
695+++ src/server/default_server_configuration.cpp 2013-04-22 21:32:25 +0000
696@@ -45,7 +45,7 @@
697 #include "mir/graphics/buffer_initializer.h"
698 #include "mir/graphics/null_display_report.h"
699 #include "mir/input/null_input_manager.h"
700-#include "mir/input/null_input_focus_selector.h"
701+#include "mir/input/null_input_target_listener.h"
702 #include "input/android/default_android_input_configuration.h"
703 #include "input/android/android_input_manager.h"
704 #include "input/android/android_dispatcher_controller.h"
705@@ -310,8 +310,7 @@
706 [this]
707 {
708 return std::make_shared<msh::SingleVisibilityFocusMechanism>(
709- the_shell_session_container(),
710- the_input_focus_selector());
711+ the_shell_session_container());
712 });
713 }
714
715@@ -347,7 +346,8 @@
716 the_shell_surface_factory(),
717 the_shell_session_container(),
718 the_shell_focus_sequence(),
719- the_shell_focus_setter());
720+ the_shell_focus_setter(),
721+ the_input_target_listener());
722 });
723 }
724
725@@ -562,15 +562,15 @@
726 return the_input_manager();
727 }
728
729-std::shared_ptr<msh::InputFocusSelector> mir::DefaultServerConfiguration::the_input_focus_selector()
730+std::shared_ptr<msh::InputTargetListener> mir::DefaultServerConfiguration::the_input_target_listener()
731 {
732- return input_focus_selector(
733- [&]() -> std::shared_ptr<msh::InputFocusSelector>
734+ return input_target_listener(
735+ [&]() -> std::shared_ptr<msh::InputTargetListener>
736 {
737 if (the_options()->get("enable-input", false))
738 return std::make_shared<mia::DispatcherController>(the_input_configuration());
739 else
740- return std::make_shared<mi::NullInputFocusSelector>();
741+ return std::make_shared<mi::NullInputTargetListener>();
742 });
743 }
744
745
746=== modified file 'src/server/display_server.cpp'
747--- src/server/display_server.cpp 2013-04-19 14:52:23 +0000
748+++ src/server/display_server.cpp 2013-04-22 21:32:25 +0000
749@@ -31,9 +31,9 @@
750
751 namespace mc = mir::compositor;
752 namespace mf = mir::frontend;
753-namespace msh = mir::shell;
754 namespace mg = mir::graphics;
755 namespace mi = mir::input;
756+namespace msh = mir::shell;
757
758 namespace
759 {
760
761=== modified file 'src/server/input/android/android_dispatcher_controller.cpp'
762--- src/server/input/android/android_dispatcher_controller.cpp 2013-04-11 23:06:12 +0000
763+++ src/server/input/android/android_dispatcher_controller.cpp 2013-04-22 21:32:25 +0000
764@@ -25,35 +25,85 @@
765
766 #include <InputDispatcher.h>
767
768+#include <boost/throw_exception.hpp>
769+
770+#include <stdexcept>
771+#include <mutex>
772+
773 namespace mi = mir::input;
774 namespace mia = mi::android;
775
776 mia::DispatcherController::DispatcherController(std::shared_ptr<mia::InputConfiguration> const& config) :
777- input_dispatcher(config->the_dispatcher()),
778- focused_window_handle(0),
779- focused_application_handle(0)
780-{
781-}
782-
783-void mia::DispatcherController::set_input_focus_to(std::shared_ptr<mi::SessionTarget> const& session,
784- std::shared_ptr<mi::SurfaceTarget> const& surface)
785-{
786- if (focused_window_handle.get())
787- {
788- input_dispatcher->unregisterInputChannel(focused_window_handle->getInfo()->inputChannel);
789- focused_window_handle.clear();
790- focused_application_handle.clear();
791- }
792+ input_dispatcher(config->the_dispatcher())
793+{
794+}
795+
796+void mia::DispatcherController::input_application_opened(std::shared_ptr<mi::SessionTarget> const& session)
797+{
798+ std::unique_lock<std::mutex> lock(handles_mutex);
799+ if (application_handles.find(session) != application_handles.end())
800+ BOOST_THROW_EXCEPTION(std::logic_error("An application was opened twice"));
801+ application_handles[session] = new mia::InputApplicationHandle(session);
802+}
803+
804+void mia::DispatcherController::input_application_closed(std::shared_ptr<mi::SessionTarget> const& session)
805+{
806+ std::unique_lock<std::mutex> lock(handles_mutex);
807+ if (application_handles.find(session) == application_handles.end())
808+ BOOST_THROW_EXCEPTION(std::logic_error("An application was closed twice"));
809+ application_handles.erase(session);
810+}
811+
812+void mia::DispatcherController::input_surface_opened(std::shared_ptr<mi::SessionTarget> const& session,
813+ std::shared_ptr<input::SurfaceTarget> const& opened_surface)
814+{
815+ std::unique_lock<std::mutex> lock(handles_mutex);
816+ auto application_handle = application_handles.find(session);
817+ if (application_handle == application_handles.end())
818+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was opened for an unopened application"));
819+ if (window_handles.find(opened_surface) != window_handles.end())
820+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was opened twice"));
821+
822+ droidinput::sp<droidinput::InputWindowHandle> window_handle = new mia::InputWindowHandle(application_handle->second, opened_surface);
823+ input_dispatcher->registerInputChannel(window_handle->getInfo()->inputChannel, window_handle, false);
824+
825+ window_handles[opened_surface] = window_handle;
826+}
827+
828+void mia::DispatcherController::input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface)
829+{
830+ std::unique_lock<std::mutex> lock(handles_mutex);
831+ auto it = window_handles.find(closed_surface);
832+ if (it == window_handles.end())
833+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was closed twice"));
834+
835+ input_dispatcher->unregisterInputChannel(it->second->getInfo()->inputChannel);
836+ window_handles.erase(it);
837+}
838+
839+void mia::DispatcherController::focus_cleared()
840+{
841+ droidinput::Vector<droidinput::sp<droidinput::InputWindowHandle>> empty_windows;
842+ droidinput::sp<droidinput::InputApplicationHandle> null_application = nullptr;
843+
844+ input_dispatcher->setFocusedApplication(null_application);
845+ input_dispatcher->setInputWindows(empty_windows);
846+}
847+
848+void mia::DispatcherController::focus_changed(std::shared_ptr<mi::SurfaceTarget> const& surface)
849+{
850+ std::unique_lock<std::mutex> lock(handles_mutex);
851+
852+ auto window_handle = window_handles[surface];
853+
854+ if (!window_handle.get())
855+ BOOST_THROW_EXCEPTION(std::logic_error("Focus changed to an unopened surface"));
856+ auto application_handle = window_handle->inputApplicationHandle;
857+
858+ input_dispatcher->setFocusedApplication(application_handle);
859
860 droidinput::Vector<droidinput::sp<droidinput::InputWindowHandle>> windows;
861- if (surface)
862- {
863- focused_application_handle = new mia::InputApplicationHandle(session);
864- focused_window_handle = new mia::InputWindowHandle(focused_application_handle, surface);
865- input_dispatcher->setFocusedApplication(focused_application_handle);
866+ windows.push_back(window_handle);
867
868- input_dispatcher->registerInputChannel(focused_window_handle->getInfo()->inputChannel, focused_window_handle, false);
869- windows.push_back(focused_window_handle);
870- }
871 input_dispatcher->setInputWindows(windows);
872 }
873
874=== modified file 'src/server/input/android/android_dispatcher_controller.h'
875--- src/server/input/android/android_dispatcher_controller.h 2013-04-11 23:06:12 +0000
876+++ src/server/input/android/android_dispatcher_controller.h 2013-04-22 21:32:25 +0000
877@@ -19,10 +19,13 @@
878 #ifndef MIR_INPUT_ANDROID_DISPATCHER_CONTROLLER_H_
879 #define MIR_INPUT_ANDROID_DISPATCHER_CONTROLLER_H_
880
881-#include "mir/shell/input_focus_selector.h"
882+#include "mir/shell/input_target_listener.h"
883
884 #include <utils/StrongPointer.h>
885
886+#include <map>
887+#include <mutex>
888+
889 namespace android
890 {
891 class InputDispatcherInterface;
892@@ -40,13 +43,21 @@
893 {
894 class InputConfiguration;
895
896-class DispatcherController : public shell::InputFocusSelector
897+class DispatcherController : public shell::InputTargetListener
898 {
899 public:
900 explicit DispatcherController(std::shared_ptr<InputConfiguration> const& input_configuration);
901- virtual ~DispatcherController() = default;
902+ virtual ~DispatcherController() noexcept(true) {}
903
904- void set_input_focus_to(std::shared_ptr<input::SessionTarget> const& session, std::shared_ptr<input::SurfaceTarget> const& surface);
905+ void input_application_opened(std::shared_ptr<input::SessionTarget> const& application);
906+ void input_application_closed(std::shared_ptr<input::SessionTarget> const& application);
907+
908+ void input_surface_opened(std::shared_ptr<input::SessionTarget> const& application,
909+ std::shared_ptr<input::SurfaceTarget> const& opened_surface);
910+ void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface);
911+
912+ void focus_changed(std::shared_ptr<input::SurfaceTarget> const& focus_surface);
913+ void focus_cleared();
914
915 protected:
916 DispatcherController(const DispatcherController&) = delete;
917@@ -55,8 +66,10 @@
918 private:
919 droidinput::sp<droidinput::InputDispatcherInterface> input_dispatcher;
920
921- droidinput::sp<droidinput::InputWindowHandle> focused_window_handle;
922- droidinput::sp<droidinput::InputApplicationHandle> focused_application_handle;
923+ std::map<std::shared_ptr<input::SessionTarget>, droidinput::sp<droidinput::InputApplicationHandle>> application_handles;
924+ std::map<std::shared_ptr<input::SurfaceTarget>, droidinput::sp<droidinput::InputWindowHandle>> window_handles;
925+
926+ std::mutex handles_mutex;
927 };
928
929 }
930
931=== modified file 'src/server/input/android/android_input_reader_policy.cpp'
932--- src/server/input/android/android_input_reader_policy.cpp 2013-04-16 09:08:29 +0000
933+++ src/server/input/android/android_input_reader_policy.cpp 2013-04-22 21:32:25 +0000
934@@ -47,7 +47,10 @@
935 width,
936 height,
937 default_display_orientation);
938+
939+ out_config->pointerVelocityControlParameters.acceleration = 1.0;
940 }
941+
942 droidinput::sp<droidinput::PointerControllerInterface> mia::InputReaderPolicy::obtainPointerController(int32_t /*device_id*/)
943 {
944 return pointer_controller;
945
946=== modified file 'src/server/input/android/android_input_window_handle.cpp'
947--- src/server/input/android/android_input_window_handle.cpp 2013-03-29 16:51:35 +0000
948+++ src/server/input/android/android_input_window_handle.cpp 2013-04-22 21:32:25 +0000
949@@ -48,11 +48,17 @@
950 surface->server_input_fd());
951 }
952
953- mInfo->frameLeft = 0;
954- mInfo->frameTop = 0;
955+ auto surface_position = surface->top_left();
956+ mInfo->frameLeft = surface_position.x.as_uint32_t();
957+ mInfo->frameTop = surface_position.y.as_uint32_t();
958 auto surface_size = surface->size();
959 mInfo->frameRight = mInfo->frameLeft + surface_size.width.as_uint32_t();
960 mInfo->frameBottom = mInfo->frameTop + surface_size.height.as_uint32_t();
961+
962+ mInfo->touchableRegionLeft = mInfo->frameLeft;
963+ mInfo->touchableRegionTop = mInfo->frameTop;
964+ mInfo->touchableRegionRight = mInfo->frameRight;
965+ mInfo->touchableRegionBottom = mInfo->frameBottom;
966
967 mInfo->name = droidinput::String8(surface->name().c_str());
968 mInfo->layoutParamsFlags = droidinput::InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
969
970=== modified file 'src/server/input/android/default_android_input_configuration.cpp'
971--- src/server/input/android/default_android_input_configuration.cpp 2013-04-16 09:08:29 +0000
972+++ src/server/input/android/default_android_input_configuration.cpp 2013-04-22 21:32:25 +0000
973@@ -98,7 +98,7 @@
974 return dispatcher_policy(
975 [this]()
976 {
977- return new mia::EventFilterDispatcherPolicy(filter_chain);
978+ return new mia::EventFilterDispatcherPolicy(filter_chain, is_key_repeat_enabled());
979 });
980 }
981
982@@ -149,3 +149,8 @@
983 new droidinput::InputReaderThread(the_reader()));
984 });
985 }
986+
987+bool mia::DefaultInputConfiguration::is_key_repeat_enabled()
988+{
989+ return true;
990+}
991
992=== modified file 'src/server/input/android/default_android_input_configuration.h'
993--- src/server/input/android/default_android_input_configuration.h 2013-04-16 09:08:29 +0000
994+++ src/server/input/android/default_android_input_configuration.h 2013-04-22 21:32:25 +0000
995@@ -69,6 +69,8 @@
996
997 virtual droidinput::sp<droidinput::InputDispatcherPolicyInterface> the_dispatcher_policy();
998 virtual droidinput::sp<droidinput::InputReaderPolicyInterface> the_reader_policy();
999+
1000+ virtual bool is_key_repeat_enabled();
1001
1002 protected:
1003 DefaultInputConfiguration(DefaultInputConfiguration const&) = delete;
1004
1005=== modified file 'src/server/input/android/event_filter_dispatcher_policy.cpp'
1006--- src/server/input/android/event_filter_dispatcher_policy.cpp 2013-04-16 09:27:00 +0000
1007+++ src/server/input/android/event_filter_dispatcher_policy.cpp 2013-04-22 21:32:25 +0000
1008@@ -21,8 +21,9 @@
1009 namespace mi = mir::input;
1010 namespace mia = mi::android;
1011
1012-mia::EventFilterDispatcherPolicy::EventFilterDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& event_filter) :
1013- event_filter(event_filter)
1014+mia::EventFilterDispatcherPolicy::EventFilterDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& event_filter, bool key_repeat_enabled) :
1015+ event_filter(event_filter),
1016+ key_repeat_enabled(key_repeat_enabled)
1017 {
1018 }
1019
1020@@ -46,7 +47,7 @@
1021
1022 bool mia::EventFilterDispatcherPolicy::isKeyRepeatEnabled()
1023 {
1024- return true;
1025+ return key_repeat_enabled;
1026 }
1027
1028 bool mia::EventFilterDispatcherPolicy::filterInputEvent(const droidinput::InputEvent* input_event, uint32_t /*policy_flags*/)
1029@@ -67,9 +68,9 @@
1030 policy_flags |= droidinput::POLICY_FLAG_PASS_TO_USER;
1031 }
1032
1033-void mia::EventFilterDispatcherPolicy::interceptMotionBeforeQueueing(nsecs_t /* when */, uint32_t& /* policyFlags */)
1034+void mia::EventFilterDispatcherPolicy::interceptMotionBeforeQueueing(nsecs_t /* when */, uint32_t& policy_flags)
1035 {
1036- // TODO: Implement for motion events to client.
1037+ policy_flags |= droidinput::POLICY_FLAG_PASS_TO_USER;
1038 }
1039
1040 nsecs_t mia::EventFilterDispatcherPolicy::interceptKeyBeforeDispatching(
1041
1042=== modified file 'src/server/input/android/event_filter_dispatcher_policy.h'
1043--- src/server/input/android/event_filter_dispatcher_policy.h 2013-04-16 09:08:29 +0000
1044+++ src/server/input/android/event_filter_dispatcher_policy.h 2013-04-22 21:32:25 +0000
1045@@ -40,7 +40,7 @@
1046 class EventFilterDispatcherPolicy : public droidinput::InputDispatcherPolicyInterface
1047 {
1048 public:
1049- EventFilterDispatcherPolicy(std::shared_ptr<EventFilter> const& event_filter);
1050+ EventFilterDispatcherPolicy(std::shared_ptr<EventFilter> const& event_filter, bool key_repeat_enabled);
1051 virtual ~EventFilterDispatcherPolicy() {}
1052
1053 void notifyConfigurationChanged(nsecs_t when);
1054@@ -71,6 +71,7 @@
1055 EventFilterDispatcherPolicy& operator=(const EventFilterDispatcherPolicy&) = delete;
1056 private:
1057 std::shared_ptr<EventFilter> event_filter;
1058+ bool key_repeat_enabled;
1059 };
1060
1061 }
1062
1063=== modified file 'src/server/shell/application_session.cpp'
1064--- src/server/shell/application_session.cpp 2013-04-16 17:42:26 +0000
1065+++ src/server/shell/application_session.cpp 2013-04-22 21:32:25 +0000
1066@@ -18,8 +18,8 @@
1067
1068 #include "mir/shell/application_session.h"
1069 #include "mir/shell/surface.h"
1070-
1071 #include "mir/shell/surface_factory.h"
1072+#include "mir/shell/input_target_listener.h"
1073
1074 #include <boost/throw_exception.hpp>
1075
1076@@ -32,9 +32,11 @@
1077 namespace msh = mir::shell;
1078
1079 msh::ApplicationSession::ApplicationSession(
1080- std::shared_ptr<SurfaceFactory> const& surface_factory,
1081+ std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
1082+ std::shared_ptr<msh::InputTargetListener> const& input_target_listener,
1083 std::string const& session_name) :
1084 surface_factory(surface_factory),
1085+ input_target_listener(input_target_listener),
1086 session_name(session_name),
1087 next_surface_id(0)
1088 {
1089@@ -46,6 +48,7 @@
1090 std::unique_lock<std::mutex> lock(surfaces_mutex);
1091 for (auto const& pair_id_surface : surfaces)
1092 {
1093+ input_target_listener->input_surface_closed(pair_id_surface.second);
1094 pair_id_surface.second->destroy();
1095 }
1096 }
1097@@ -95,6 +98,7 @@
1098 std::unique_lock<std::mutex> lock(surfaces_mutex);
1099 auto p = checked_find(id);
1100
1101+ input_target_listener->input_surface_closed(p->second);
1102 p->second->destroy();
1103 surfaces.erase(p);
1104 }
1105
1106=== modified file 'src/server/shell/session_manager.cpp'
1107--- src/server/shell/session_manager.cpp 2013-04-19 09:15:31 +0000
1108+++ src/server/shell/session_manager.cpp 2013-04-22 21:32:25 +0000
1109@@ -23,6 +23,8 @@
1110 #include "mir/shell/focus_sequence.h"
1111 #include "mir/shell/focus_setter.h"
1112 #include "mir/shell/session.h"
1113+#include "mir/shell/surface.h"
1114+#include "mir/shell/input_target_listener.h"
1115
1116 #include <memory>
1117 #include <cassert>
1118@@ -31,20 +33,22 @@
1119 namespace mf = mir::frontend;
1120 namespace msh = mir::shell;
1121
1122-msh::SessionManager::SessionManager(
1123- std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
1124+msh::SessionManager::SessionManager(std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
1125 std::shared_ptr<msh::SessionContainer> const& container,
1126 std::shared_ptr<msh::FocusSequence> const& sequence,
1127- std::shared_ptr<msh::FocusSetter> const& focus_setter) :
1128+ std::shared_ptr<msh::FocusSetter> const& focus_setter,
1129+ std::shared_ptr<msh::InputTargetListener> const& input_target_listener) :
1130 surface_factory(surface_factory),
1131 app_container(container),
1132 focus_sequence(sequence),
1133- focus_setter(focus_setter)
1134+ focus_setter(focus_setter),
1135+ input_target_listener(input_target_listener)
1136 {
1137 assert(surface_factory);
1138 assert(sequence);
1139 assert(container);
1140 assert(focus_setter);
1141+ assert(input_target_listener);
1142 }
1143
1144 msh::SessionManager::~SessionManager()
1145@@ -53,25 +57,36 @@
1146
1147 std::shared_ptr<mf::Session> msh::SessionManager::open_session(std::string const& name)
1148 {
1149- auto new_session = std::make_shared<msh::ApplicationSession>(surface_factory, name);
1150+ auto new_session = std::make_shared<msh::ApplicationSession>(surface_factory, input_target_listener, name);
1151
1152 app_container->insert_session(new_session);
1153+
1154+ input_target_listener->input_application_opened(new_session);
1155
1156 set_focus_to_locked(std::unique_lock<std::mutex>(mutex), new_session);
1157
1158 return new_session;
1159 }
1160
1161-inline void msh::SessionManager::set_focus_to_locked(std::unique_lock<std::mutex> const&, std::shared_ptr<Session> const& next_focus)
1162+inline void msh::SessionManager::set_focus_to_locked(std::unique_lock<std::mutex> const&, std::shared_ptr<Session> const& shell_session)
1163 {
1164- focus_application = next_focus;
1165- focus_setter->set_focus_to(next_focus);
1166+ auto old_focus = focus_application.lock();
1167+
1168+ focus_application = shell_session;
1169+ focus_setter->set_focus_to(shell_session);
1170+
1171+ if (shell_session && shell_session->default_surface())
1172+ input_target_listener->focus_changed(shell_session->default_surface());
1173+ else if (shell_session == old_focus || !shell_session)
1174+ input_target_listener->focus_cleared();
1175 }
1176
1177 void msh::SessionManager::close_session(std::shared_ptr<mf::Session> const& session)
1178 {
1179 auto shell_session = std::dynamic_pointer_cast<Session>(session);
1180
1181+ input_target_listener->input_application_closed(shell_session);
1182+
1183 app_container->remove_session(shell_session);
1184
1185 std::unique_lock<std::mutex> lock(mutex);
1186@@ -133,9 +148,11 @@
1187 mf::SurfaceCreationParameters const& params)
1188 {
1189 auto shell_session = std::dynamic_pointer_cast<Session>(session);
1190- auto id = session->create_surface(params);
1191+ auto id = shell_session->create_surface(params);
1192+
1193+ input_target_listener->input_surface_opened(shell_session,
1194+ std::dynamic_pointer_cast<msh::Surface>(shell_session->get_surface(id)));
1195 set_focus_to_locked(std::unique_lock<std::mutex>(mutex), shell_session);
1196
1197 return id;
1198 }
1199-
1200
1201=== modified file 'src/server/shell/single_visibility_focus_mechanism.cpp'
1202--- src/server/shell/single_visibility_focus_mechanism.cpp 2013-04-18 22:57:01 +0000
1203+++ src/server/shell/single_visibility_focus_mechanism.cpp 2013-04-22 21:32:25 +0000
1204@@ -19,7 +19,6 @@
1205 #include "mir/shell/session_container.h"
1206 #include "mir/frontend/session.h"
1207 #include "mir/shell/single_visibility_focus_mechanism.h"
1208-#include "mir/shell/input_focus_selector.h"
1209
1210 #include "mir/shell/session.h"
1211 #include "mir/shell/surface.h"
1212@@ -27,10 +26,8 @@
1213 namespace mf = mir::frontend;
1214 namespace msh = mir::shell;
1215
1216-msh::SingleVisibilityFocusMechanism::SingleVisibilityFocusMechanism(std::shared_ptr<msh::SessionContainer> const& app_container,
1217- std::shared_ptr<msh::InputFocusSelector> const& input_selector)
1218- : app_container(app_container),
1219- input_selector(input_selector)
1220+msh::SingleVisibilityFocusMechanism::SingleVisibilityFocusMechanism(std::shared_ptr<msh::SessionContainer> const& app_container)
1221+ : app_container(app_container)
1222 {
1223 }
1224
1225@@ -41,8 +38,6 @@
1226 if (session == focus_session)
1227 {
1228 session->show();
1229-
1230- input_selector->set_input_focus_to(focus_session, focus_session->default_surface());
1231 }
1232 else
1233 {
1234
1235=== modified file 'src/server/shell/surface.cpp'
1236--- src/server/shell/surface.cpp 2013-04-16 17:42:26 +0000
1237+++ src/server/shell/surface.cpp 2013-04-22 21:32:25 +0000
1238@@ -88,6 +88,18 @@
1239 }
1240 }
1241
1242+mir::geometry::Point msh::Surface::top_left() const
1243+{
1244+ if (auto const& s = surface.lock())
1245+ {
1246+ return s->top_left();
1247+ }
1248+ else
1249+ {
1250+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
1251+ }
1252+}
1253+
1254 std::string msh::Surface::name() const
1255 {
1256 if (auto const& s = surface.lock())
1257
1258=== modified file 'tests/acceptance-tests/test_client_input.cpp'
1259--- tests/acceptance-tests/test_client_input.cpp 2013-04-17 07:31:40 +0000
1260+++ tests/acceptance-tests/test_client_input.cpp 2013-04-22 21:32:25 +0000
1261@@ -65,10 +65,9 @@
1262
1263 }
1264
1265- void set_input_focus_to(
1266- std::shared_ptr<mi::SessionTarget> const& session, std::shared_ptr<mi::SurfaceTarget> const& surface) override
1267+ void focus_changed(std::shared_ptr<mi::SurfaceTarget> const& surface) override
1268 {
1269- DispatcherController::set_input_focus_to(session, surface);
1270+ DispatcherController::focus_changed(surface);
1271
1272 // We need a synchronization primitive inorder to halt test event injection
1273 // until after a surface has taken focus (lest the events be discarded).
1274@@ -96,6 +95,7 @@
1275 {
1276 on_focus_set.wait_for_at_most_seconds(10);
1277 fake_event_hub->synthesize_builtin_keyboard_added();
1278+ fake_event_hub->synthesize_builtin_cursor_added();
1279 fake_event_hub->synthesize_device_scan_complete();
1280 inject_input();
1281 });
1282@@ -122,10 +122,10 @@
1283 });
1284 }
1285
1286- std::shared_ptr<msh::InputFocusSelector>
1287- the_input_focus_selector() override
1288+ std::shared_ptr<msh::InputTargetListener>
1289+ the_input_target_listener() override
1290 {
1291- return input_focus_selector(
1292+ return input_target_listener(
1293 [this]()
1294 {
1295 return std::make_shared<FocusNotifyingDispatcherController>(mt::fake_shared(input_config), on_focus_set);
1296@@ -186,7 +186,7 @@
1297
1298 struct MockInputHandler
1299 {
1300- MOCK_METHOD1(handle_key_down, void(MirEvent const*));
1301+ MOCK_METHOD1(handle_input, bool(MirEvent const*));
1302 };
1303
1304 struct InputReceivingClient : ClientConfigCommon
1305@@ -201,9 +201,9 @@
1306 static void handle_input(MirSurface* /* surface */, MirEvent const* ev, void* context)
1307 {
1308 auto client = static_cast<InputReceivingClient *>(context);
1309- if (ev->key.action == 0)
1310+
1311+ if(client->handler->handle_input(ev))
1312 {
1313- client->handler->handle_key_down(ev);
1314 client->event_received[client->events_received].wake_up_everyone();
1315 client->events_received++;
1316 }
1317@@ -227,7 +227,7 @@
1318 MirSurfaceParameters const request_params =
1319 {
1320 __PRETTY_FUNCTION__,
1321- 640, 480,
1322+ surface_width, surface_height,
1323 mir_pixel_format_abgr_8888,
1324 mir_buffer_usage_hardware
1325 };
1326@@ -259,9 +259,66 @@
1327
1328 int events_to_receive;
1329 int events_received;
1330+
1331+ static int const surface_width = 100;
1332+ static int const surface_height = 100;
1333 };
1334
1335-}
1336+MATCHER(KeyDownEvent, "")
1337+{
1338+ if (arg->type != mir_event_type_key)
1339+ return false;
1340+ if (arg->key.action != 0) // Key down
1341+ return false;
1342+
1343+ return true;
1344+}
1345+MATCHER_P(KeyOfSymbol, keysym, "")
1346+{
1347+ if (static_cast<xkb_keysym_t>(arg->key.key_code) == (uint)keysym)
1348+ return true;
1349+ return false;
1350+}
1351+
1352+MATCHER(HoverEnterEvent, "")
1353+{
1354+ if (arg->type != mir_event_type_motion)
1355+ return false;
1356+ if (arg->motion.action != AMOTION_EVENT_ACTION_HOVER_ENTER)
1357+ return false;
1358+
1359+ return true;
1360+}
1361+
1362+MATCHER_P2(ButtonDownEvent, x, y, "")
1363+{
1364+ if (arg->type != mir_event_type_motion)
1365+ return false;
1366+ if (arg->motion.action != AMOTION_EVENT_ACTION_DOWN)
1367+ return false;
1368+ printf("action: %d \n", arg->motion.action);
1369+ if (arg->motion.button_state == 0)
1370+ return false;
1371+ if (arg->motion.pointer_coordinates[0].x != x)
1372+ return false;
1373+ if (arg->motion.pointer_coordinates[0].y != y)
1374+ return false;
1375+ return true;
1376+}
1377+
1378+MATCHER_P2(MotionEventWithPosition, x, y, "")
1379+{
1380+ if (arg->type != mir_event_type_motion)
1381+ return false;
1382+ if (arg->motion.pointer_coordinates[0].x != x)
1383+ return false;
1384+ if (arg->motion.pointer_coordinates[0].y != y)
1385+ return false;
1386+ return true;
1387+}
1388+
1389+}
1390+
1391
1392 using TestClientInput = BespokeDisplayServerTestFixture;
1393
1394@@ -290,22 +347,13 @@
1395 void expect_input()
1396 {
1397 using namespace ::testing;
1398- EXPECT_CALL(*handler, handle_key_down(_)).Times(num_events_produced);
1399+ EXPECT_CALL(*handler, handle_input(KeyDownEvent())).Times(num_events_produced)
1400+ .WillRepeatedly(Return(true));
1401 }
1402 } client_config;
1403 launch_client_process(client_config);
1404 }
1405
1406-namespace
1407-{
1408-MATCHER_P(KeyOfSymbol, keysym, "")
1409-{
1410- if (static_cast<xkb_keysym_t>(arg->key.key_code) == (uint)keysym)
1411- return true;
1412- return false;
1413-}
1414-}
1415-
1416 TEST_F(TestClientInput, clients_receive_us_english_mapped_keys)
1417 {
1418 using namespace ::testing;
1419@@ -319,12 +367,6 @@
1420 fake_event_hub->synthesize_event(mis::a_key_down_event()
1421 .of_scancode(KEY_4));
1422
1423- // Release the keys so we don't get repeat events.
1424- fake_event_hub->synthesize_event(mis::a_key_up_event()
1425- .of_scancode(KEY_4));
1426- fake_event_hub->synthesize_event(mis::a_key_up_event()
1427- .of_scancode(KEY_LEFTSHIFT));
1428-
1429 }
1430 } server_config;
1431 launch_server_process(server_config);
1432@@ -338,10 +380,78 @@
1433 using namespace ::testing;
1434
1435 InSequence seq;
1436- EXPECT_CALL(*handler, handle_key_down(KeyOfSymbol(XKB_KEY_Shift_L))).Times(1);
1437- EXPECT_CALL(*handler, handle_key_down(KeyOfSymbol(XKB_KEY_dollar))).Times(1);
1438- }
1439- } client_config;
1440- launch_client_process(client_config);
1441-}
1442-
1443+ EXPECT_CALL(*handler, handle_input(AllOf(KeyDownEvent(), KeyOfSymbol(XKB_KEY_Shift_L)))).Times(1)
1444+ .WillOnce(Return(true));
1445+ EXPECT_CALL(*handler, handle_input(AllOf(KeyDownEvent(), KeyOfSymbol(XKB_KEY_dollar)))).Times(1)
1446+ .WillOnce(Return(true));
1447+ }
1448+ } client_config;
1449+ launch_client_process(client_config);
1450+}
1451+
1452+// TODO: This assumes that clients are placed by shell at 0,0. Which probably isn't quite safe!
1453+TEST_F(TestClientInput, clients_receive_motion_inside_window)
1454+{
1455+ using namespace ::testing;
1456+
1457+ struct InputProducingServerConfiguration : FakeInputServerConfiguration
1458+ {
1459+ void inject_input()
1460+ {
1461+ fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(InputReceivingClient::surface_width,
1462+ InputReceivingClient::surface_height));
1463+ fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(2,2));
1464+ }
1465+ } server_config;
1466+ launch_server_process(server_config);
1467+
1468+ struct MotionReceivingClient : InputReceivingClient
1469+ {
1470+ MotionReceivingClient() : InputReceivingClient(2) {}
1471+
1472+ void expect_input()
1473+ {
1474+ using namespace ::testing;
1475+
1476+ InSequence seq;
1477+
1478+ // We should see the cursor enter
1479+ EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(1).WillOnce(Return(true));
1480+ EXPECT_CALL(*handler, handle_input(
1481+ MotionEventWithPosition(InputReceivingClient::surface_width,
1482+ InputReceivingClient::surface_height))).Times(1).WillOnce(Return(true));
1483+ // But we should not receive an event for the second movement outside of our surface!
1484+ }
1485+ } client_config;
1486+ launch_client_process(client_config);
1487+}
1488+
1489+TEST_F(TestClientInput, clients_receive_button_events_inside_window)
1490+{
1491+ using namespace ::testing;
1492+
1493+ struct InputProducingServerConfiguration : FakeInputServerConfiguration
1494+ {
1495+ void inject_input()
1496+ {
1497+ fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
1498+ }
1499+ } server_config;
1500+ launch_server_process(server_config);
1501+
1502+ struct ButtonReceivingClient : InputReceivingClient
1503+ {
1504+ ButtonReceivingClient() : InputReceivingClient(1) {}
1505+
1506+ void expect_input()
1507+ {
1508+ using namespace ::testing;
1509+
1510+ InSequence seq;
1511+
1512+ // The cursor starts at (0, 0).
1513+ EXPECT_CALL(*handler, handle_input(ButtonDownEvent(0, 0))).Times(1).WillOnce(Return(true));
1514+ }
1515+ } client_config;
1516+ launch_client_process(client_config);
1517+}
1518
1519=== modified file 'tests/acceptance-tests/test_focus_selection.cpp'
1520--- tests/acceptance-tests/test_focus_selection.cpp 2013-04-18 02:52:30 +0000
1521+++ tests/acceptance-tests/test_focus_selection.cpp 2013-04-22 21:32:25 +0000
1522@@ -24,11 +24,11 @@
1523 #include "mir/shell/organising_surface_factory.h"
1524 #include "mir/shell/session_manager.h"
1525 #include "mir/graphics/display.h"
1526-#include "mir/shell/input_focus_selector.h"
1527+#include "mir/shell/input_target_listener.h"
1528
1529 #include "mir_test_framework/display_server_test_fixture.h"
1530 #include "mir_test_doubles/mock_focus_setter.h"
1531-#include "mir_test_doubles/mock_input_focus_selector.h"
1532+#include "mir_test_doubles/mock_input_target_listener.h"
1533
1534 #include <gtest/gtest.h>
1535 #include <gmock/gmock.h>
1536@@ -36,7 +36,8 @@
1537 namespace mf = mir::frontend;
1538 namespace msh = mir::shell;
1539 namespace mi = mir::input;
1540-namespace mtd = mir::test::doubles;
1541+namespace mt = mir::test;
1542+namespace mtd = mt::doubles;
1543 namespace mtf = mir_test_framework;
1544
1545 namespace
1546@@ -46,6 +47,7 @@
1547
1548 namespace
1549 {
1550+
1551 struct ClientConfigCommon : TestingClientConfiguration
1552 {
1553 ClientConfigCommon() :
1554@@ -121,18 +123,10 @@
1555 {
1556 return arg != std::shared_ptr<msh::Session>();
1557 }
1558-MATCHER(NonNullSessionTarget, "")
1559-{
1560- return arg != std::shared_ptr<mi::SessionTarget>();
1561-}
1562 MATCHER(NonNullSurfaceTarget, "")
1563 {
1564 return arg != std::shared_ptr<mi::SurfaceTarget>();
1565 }
1566-MATCHER(NullSurfaceTarget, "")
1567-{
1568- return arg == std::shared_ptr<mi::SurfaceTarget>();
1569-}
1570 }
1571
1572 TEST_F(BespokeDisplayServerTestFixture, sessions_creating_surface_receive_focus)
1573@@ -148,7 +142,6 @@
1574 using namespace ::testing;
1575
1576 auto focus_setter = std::make_shared<mtd::MockFocusSetter>();
1577-
1578 {
1579 InSequence seq;
1580 // Once on application registration and once on surface creation
1581@@ -174,30 +167,37 @@
1582 {
1583 struct ServerConfig : TestingServerConfiguration
1584 {
1585- std::shared_ptr<mtd::MockInputFocusSelector> focus_selector;
1586+ std::shared_ptr<mtd::MockInputTargetListener> target_listener;
1587 bool expected;
1588
1589 ServerConfig()
1590- : focus_selector(std::make_shared<mtd::MockInputFocusSelector>()),
1591+ : target_listener(std::make_shared<mtd::MockInputTargetListener>()),
1592 expected(false)
1593 {
1594 }
1595
1596- std::shared_ptr<msh::InputFocusSelector>
1597- the_input_focus_selector() override
1598+ std::shared_ptr<msh::InputTargetListener>
1599+ the_input_target_listener() override
1600 {
1601 using namespace ::testing;
1602
1603 if (!expected)
1604 {
1605- InSequence seq;
1606+
1607+ EXPECT_CALL(*target_listener, input_application_opened(_)).Times(AtLeast(0));
1608+ EXPECT_CALL(*target_listener, input_application_closed(_)).Times(AtLeast(0));
1609+ EXPECT_CALL(*target_listener, input_surface_opened(_,_)).Times(AtLeast(0));
1610+ EXPECT_CALL(*target_listener, input_surface_closed(_)).Times(AtLeast(0));
1611+ EXPECT_CALL(*target_listener, focus_cleared()).Times(AtLeast(0));
1612
1613- EXPECT_CALL(*focus_selector, set_input_focus_to(NonNullSessionTarget(), NullSurfaceTarget())).Times(1);
1614- EXPECT_CALL(*focus_selector, set_input_focus_to(NonNullSessionTarget(), NonNullSurfaceTarget())).Times(1);
1615- expected = true;
1616+ {
1617+ InSequence seq;
1618+ EXPECT_CALL(*target_listener, focus_changed(NonNullSurfaceTarget())).Times(1);
1619+ expected = true;
1620+ }
1621 }
1622
1623- return focus_selector;
1624+ return target_listener;
1625 }
1626 } server_config;
1627
1628
1629=== modified file 'tests/death-tests/test_application_manager_death.cpp'
1630--- tests/death-tests/test_application_manager_death.cpp 2013-03-21 03:32:59 +0000
1631+++ tests/death-tests/test_application_manager_death.cpp 2013-04-22 21:32:25 +0000
1632@@ -30,11 +30,12 @@
1633 // ::testing::FLAGS_gtest_death_test_style = "threadsafe";
1634 // leads to the test failing under valgrind
1635 EXPECT_EXIT(
1636- std::shared_ptr<msh::SurfaceFactory> factory;
1637- mir::shell::SessionManager app(factory,
1638+ std::shared_ptr<msh::SurfaceFactory> surface_factory;
1639+ mir::shell::SessionManager app(surface_factory,
1640 std::shared_ptr<msh::SessionContainer>(),
1641 std::shared_ptr<msh::FocusSequence>(),
1642- std::shared_ptr<msh::FocusSetter>()),
1643+ std::shared_ptr<msh::FocusSetter>(),
1644+ std::shared_ptr<msh::InputTargetListener>()),
1645 ::testing::KilledBySignal(SIGABRT),
1646 ".*");
1647 }
1648
1649=== modified file 'tests/integration-tests/input/android/test_android_input_manager.cpp'
1650--- tests/integration-tests/input/android/test_android_input_manager.cpp 2013-04-10 23:48:23 +0000
1651+++ tests/integration-tests/input/android/test_android_input_manager.cpp 2013-04-22 21:32:25 +0000
1652@@ -35,6 +35,7 @@
1653 #include "mir_test_doubles/stub_surface_target.h"
1654 #include "mir_test/wait_condition.h"
1655 #include "mir_test/event_factory.h"
1656+#include "mir_test/event_matchers.h"
1657
1658 #include <EventHub.h>
1659 #include <InputDispatcher.h>
1660@@ -171,7 +172,7 @@
1661 struct MockDispatcherPolicy : public mia::EventFilterDispatcherPolicy
1662 {
1663 MockDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& filter)
1664- : EventFilterDispatcherPolicy(filter)
1665+ : EventFilterDispatcherPolicy(filter, false)
1666 {
1667 }
1668 MOCK_METHOD3(interceptKeyBeforeDispatching, nsecs_t(droidinput::sp<droidinput::InputWindowHandle> const&,
1669@@ -211,24 +212,31 @@
1670 ON_CALL(viewable_area, view_area())
1671 .WillByDefault(Return(default_view_area));
1672 input_manager = std::make_shared<mia::InputManager>(configuration);
1673- input_focus_selector = std::make_shared<mia::DispatcherController>(configuration);
1674+ input_target_listener = std::make_shared<mia::DispatcherController>(configuration);
1675
1676 dispatcher_policy = configuration->the_mock_dispatcher_policy();
1677
1678 }
1679
1680+ ~AndroidInputManagerDispatcherInterceptSetup()
1681+ {
1682+ input_manager->stop();
1683+ }
1684+
1685 // TODO: It would be nice if it were possible to mock the interface between
1686 // droidinput::InputChannel and droidinput::InputDispatcher rather than use
1687 // valid fds to allow non-throwing construction of a real input channel.
1688 void SetUp()
1689 {
1690- test_input_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1691 input_manager->start();
1692 }
1693- void TearDown()
1694+
1695+ int test_fd()
1696 {
1697- input_manager->stop();
1698- close(test_input_fd);
1699+ int fds[2];
1700+ // Closed by droidinput InputChannel on shutdown
1701+ socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds);
1702+ return fds[0];
1703 }
1704
1705 MockEventFilter event_filter;
1706@@ -238,9 +246,7 @@
1707 droidinput::sp<MockDispatcherPolicy> dispatcher_policy;
1708
1709 std::shared_ptr<mia::InputManager> input_manager;
1710- std::shared_ptr<msh::InputFocusSelector> input_focus_selector;
1711-
1712- int test_input_fd;
1713+ std::shared_ptr<msh::InputTargetListener> input_target_listener;
1714 };
1715
1716 MATCHER_P(WindowHandleWithInputFd, input_fd, "")
1717@@ -259,14 +265,18 @@
1718 mt::WaitCondition wait_condition;
1719
1720 mtd::StubSessionTarget session;
1721- mtd::StubSurfaceTarget surface(test_input_fd);
1722+
1723+ auto input_fd = test_fd();
1724+ mtd::StubSurfaceTarget surface(input_fd);
1725
1726 EXPECT_CALL(event_filter, handles(_)).Times(1).WillOnce(Return(false));
1727 // We return -1 here to skip publishing of the event (to an unconnected test socket!).
1728- EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(test_input_fd), _, _))
1729+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd), _, _))
1730 .Times(1).WillOnce(DoAll(mt::WakeUp(&wait_condition), Return(-1)));
1731
1732- input_focus_selector->set_input_focus_to(mt::fake_shared(session), mt::fake_shared(surface));
1733+ input_target_listener->input_application_opened(mt::fake_shared(session));
1734+ input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface));
1735+ input_target_listener->focus_changed(mt::fake_shared(surface));
1736
1737 fake_event_hub->synthesize_builtin_keyboard_added();
1738 fake_event_hub->synthesize_device_scan_complete();
1739@@ -275,3 +285,52 @@
1740
1741 wait_condition.wait_for_at_most_seconds(1);
1742 }
1743+
1744+TEST_F(AndroidInputManagerDispatcherInterceptSetup, changing_focus_changes_event_recipient)
1745+{
1746+ using namespace ::testing;
1747+
1748+ mt::WaitCondition wait1, wait2, wait3;
1749+
1750+ mtd::StubSessionTarget session;
1751+
1752+ auto input_fd_1 = test_fd();
1753+ mtd::StubSurfaceTarget surface1(input_fd_1);
1754+ auto input_fd_2 = test_fd();
1755+ mtd::StubSurfaceTarget surface2(input_fd_2);
1756+
1757+ input_target_listener->input_application_opened(mt::fake_shared(session));
1758+ input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface1));
1759+ input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface2));
1760+
1761+ EXPECT_CALL(event_filter, handles(_)).Times(3).WillRepeatedly(Return(false));
1762+
1763+ {
1764+ InSequence seq;
1765+
1766+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd_1), _, _))
1767+ .Times(1).WillOnce(DoAll(mt::WakeUp(&wait1), Return(-1)));
1768+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd_2), _, _))
1769+ .Times(1).WillOnce(DoAll(mt::WakeUp(&wait2), Return(-1)));
1770+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd_1), _, _))
1771+ .Times(1).WillOnce(DoAll(mt::WakeUp(&wait3), Return(-1)));
1772+ }
1773+
1774+ fake_event_hub->synthesize_builtin_keyboard_added();
1775+ fake_event_hub->synthesize_device_scan_complete();
1776+
1777+ input_target_listener->focus_changed(mt::fake_shared(surface1));
1778+ fake_event_hub->synthesize_event(mis::a_key_down_event()
1779+ .of_scancode(KEY_1));
1780+ wait1.wait_for_at_most_seconds(1);
1781+
1782+ input_target_listener->focus_changed(mt::fake_shared(surface2));
1783+ fake_event_hub->synthesize_event(mis::a_key_down_event()
1784+ .of_scancode(KEY_2));
1785+ wait2.wait_for_at_most_seconds(1);
1786+
1787+ input_target_listener->focus_changed(mt::fake_shared(surface1));
1788+ fake_event_hub->synthesize_event(mis::a_key_down_event()
1789+ .of_scancode(KEY_3));
1790+ wait3.wait_for_at_most_seconds(5);
1791+}
1792
1793=== modified file 'tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp'
1794--- tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 2013-04-02 18:26:40 +0000
1795+++ tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 2013-04-22 21:32:25 +0000
1796@@ -26,6 +26,7 @@
1797 #include "mir_test_doubles/mock_event_filter.h"
1798 #include "mir_test/wait_condition.h"
1799 #include "mir_test/event_factory.h"
1800+#include "mir_test/event_matchers.h"
1801
1802 #include <InputDispatcher.h>
1803 #include <InputReader.h>
1804@@ -56,7 +57,7 @@
1805 void SetUp()
1806 {
1807 event_hub = new mia::FakeEventHub();
1808- dispatcher_policy = new mia::EventFilterDispatcherPolicy(mt::fake_shared(event_filter));
1809+ dispatcher_policy = new mia::EventFilterDispatcherPolicy(mt::fake_shared(event_filter), false);
1810 reader_policy = new mia::RudimentaryInputReaderPolicy();
1811 dispatcher = new droidinput::InputDispatcher(dispatcher_policy);
1812 reader = new droidinput::InputReader(event_hub, reader_policy, dispatcher);
1813
1814=== modified file 'tests/integration-tests/shell/test_session_manager.cpp'
1815--- tests/integration-tests/shell/test_session_manager.cpp 2013-04-18 00:00:55 +0000
1816+++ tests/integration-tests/shell/test_session_manager.cpp 2013-04-22 21:32:25 +0000
1817@@ -33,6 +33,7 @@
1818 #include "mir_test/fake_shared.h"
1819 #include "mir_test_doubles/mock_surface_factory.h"
1820 #include "mir_test_doubles/mock_focus_setter.h"
1821+#include "mir_test_doubles/stub_input_target_listener.h"
1822
1823 namespace mc = mir::compositor;
1824 namespace mf = mir::frontend;
1825@@ -44,19 +45,22 @@
1826 TEST(TestSessionManagerAndFocusSelectionStrategy, cycle_focus)
1827 {
1828 using namespace ::testing;
1829+
1830 mtd::MockSurfaceFactory surface_factory;
1831 std::shared_ptr<msh::DefaultSessionContainer> container(new msh::DefaultSessionContainer());
1832 msh::RegistrationOrderFocusSequence sequence(container);
1833- mtd::MockFocusSetter focus_changer;
1834+ mtd::MockFocusSetter focus_setter;
1835 std::shared_ptr<mf::Session> new_session;
1836+ mtd::StubInputTargetListener input_target_listener;
1837
1838 msh::SessionManager session_manager(
1839 mt::fake_shared(surface_factory),
1840 container,
1841 mt::fake_shared(sequence),
1842- mt::fake_shared(focus_changer));
1843-
1844- EXPECT_CALL(focus_changer, set_focus_to(_)).Times(3);
1845+ mt::fake_shared(focus_setter),
1846+ mt::fake_shared(input_target_listener));
1847+
1848+ EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
1849
1850 auto session1 = session_manager.open_session("Visual Basic Studio");
1851 auto session2 = session_manager.open_session("Microsoft Access");
1852@@ -64,9 +68,9 @@
1853
1854 {
1855 InSequence seq;
1856- EXPECT_CALL(focus_changer, set_focus_to(Eq(session1))).Times(1);
1857- EXPECT_CALL(focus_changer, set_focus_to(Eq(session2))).Times(1);
1858- EXPECT_CALL(focus_changer, set_focus_to(Eq(session3))).Times(1);
1859+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session1))).Times(1);
1860+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session2))).Times(1);
1861+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session3))).Times(1);
1862 }
1863
1864 session_manager.focus_next();
1865@@ -77,19 +81,22 @@
1866 TEST(TestSessionManagerAndFocusSelectionStrategy, closing_applications_transfers_focus)
1867 {
1868 using namespace ::testing;
1869+
1870 mtd::MockSurfaceFactory surface_factory;
1871- std::shared_ptr<msh::DefaultSessionContainer> model(new msh::DefaultSessionContainer());
1872- msh::RegistrationOrderFocusSequence sequence(model);
1873- mtd::MockFocusSetter focus_changer;
1874+ std::shared_ptr<msh::DefaultSessionContainer> container(new msh::DefaultSessionContainer());
1875+ msh::RegistrationOrderFocusSequence sequence(container);
1876+ mtd::MockFocusSetter focus_setter;
1877 std::shared_ptr<mf::Session> new_session;
1878+ mtd::StubInputTargetListener input_target_listener;
1879
1880 msh::SessionManager session_manager(
1881- mt::fake_shared(surface_factory),
1882- model,
1883- mt::fake_shared(sequence),
1884- mt::fake_shared(focus_changer));
1885+ mt::fake_shared(surface_factory),
1886+ container,
1887+ mt::fake_shared(sequence),
1888+ mt::fake_shared(focus_setter),
1889+ mt::fake_shared(input_target_listener));
1890
1891- EXPECT_CALL(focus_changer, set_focus_to(_)).Times(3);
1892+ EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
1893
1894 auto session1 = session_manager.open_session("Visual Basic Studio");
1895 auto session2 = session_manager.open_session("Microsoft Access");
1896@@ -97,8 +104,8 @@
1897
1898 {
1899 InSequence seq;
1900- EXPECT_CALL(focus_changer, set_focus_to(Eq(session2))).Times(1);
1901- EXPECT_CALL(focus_changer, set_focus_to(Eq(session1))).Times(1);
1902+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session2))).Times(1);
1903+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session1))).Times(1);
1904 }
1905
1906 session_manager.close_session(session3);
1907
1908=== modified file 'tests/mir_test_doubles/fake_event_hub.cpp'
1909--- tests/mir_test_doubles/fake_event_hub.cpp 2013-03-29 16:51:35 +0000
1910+++ tests/mir_test_doubles/fake_event_hub.cpp 2013-04-22 21:32:25 +0000
1911@@ -322,7 +322,7 @@
1912 void mia::FakeEventHub::synthesize_event(const mis::ButtonParameters &parameters)
1913 {
1914 RawEvent event;
1915- event.when = 0; // TODO: This may need a timestamp to go over the wire ~racarr
1916+ event.when = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
1917 event.type = EV_KEY;
1918 event.code = parameters.button;
1919
1920@@ -348,7 +348,7 @@
1921 void mia::FakeEventHub::synthesize_event(const mis::MotionParameters &parameters)
1922 {
1923 RawEvent event;
1924- event.when = 0;
1925+ event.when = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
1926 event.type = EV_REL;
1927 if (parameters.device_id)
1928 event.deviceId = parameters.device_id;
1929
1930=== modified file 'tests/mir_test_framework/testing_server_options.cpp'
1931--- tests/mir_test_framework/testing_server_options.cpp 2013-04-18 15:20:45 +0000
1932+++ tests/mir_test_framework/testing_server_options.cpp 2013-04-22 21:32:25 +0000
1933@@ -29,7 +29,7 @@
1934 #include "mir/compositor/graphic_buffer_allocator.h"
1935 #include "mir/input/input_channel.h"
1936 #include "mir/input/input_manager.h"
1937-#include "mir/shell/input_focus_selector.h"
1938+#include "mir/input/null_input_target_listener.h"
1939 #include "src/server/input/android/android_input_manager.h"
1940 #include "src/server/input/android/android_dispatcher_controller.h"
1941
1942@@ -159,14 +159,6 @@
1943 }
1944 };
1945
1946-class StubInputFocusSelector : public msh::InputFocusSelector
1947-{
1948-public:
1949- void set_input_focus_to(std::shared_ptr<mi::SessionTarget> const& /* session */, std::shared_ptr<mi::SurfaceTarget> const& /* surface */)
1950- {
1951- }
1952-};
1953-
1954 }
1955
1956 mtf::TestingServerConfiguration::TestingServerConfiguration() :
1957@@ -184,14 +176,14 @@
1958 return std::make_shared<StubInputManager>();
1959 }
1960
1961-std::shared_ptr<msh::InputFocusSelector> mtf::TestingServerConfiguration::the_input_focus_selector()
1962+std::shared_ptr<msh::InputTargetListener> mtf::TestingServerConfiguration::the_input_target_listener()
1963 {
1964 auto options = the_options();
1965
1966 if (options->get("tests-use-real-input", false))
1967 return std::make_shared<mia::DispatcherController>(the_input_configuration());
1968 else
1969- return std::make_shared<StubInputFocusSelector>();
1970+ return std::make_shared<mi::NullInputTargetListener>();
1971 }
1972
1973 std::shared_ptr<mg::Platform> mtf::TestingServerConfiguration::the_graphics_platform()
1974
1975=== modified file 'tests/unit-tests/input/android/test_android_dispatcher_controller.cpp'
1976--- tests/unit-tests/input/android/test_android_dispatcher_controller.cpp 2013-04-15 14:39:18 +0000
1977+++ tests/unit-tests/input/android/test_android_dispatcher_controller.cpp 2013-04-22 21:32:25 +0000
1978@@ -31,6 +31,8 @@
1979 #include <sys/types.h>
1980 #include <sys/socket.h>
1981
1982+#include <stdexcept>
1983+
1984 namespace mi = mir::input;
1985 namespace mia = mi::android;
1986 namespace mt = mir::test;
1987@@ -47,12 +49,16 @@
1988 void SetUp() override
1989 {
1990 test_input_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1991+
1992+ dispatcher = new mtd::MockInputDispatcher();
1993 }
1994 void TearDown() override
1995 {
1996 close(test_input_fd);
1997 }
1998 int test_input_fd;
1999+ droidinput::sp<mtd::MockInputDispatcher> dispatcher;
2000+ mtd::MockInputConfiguration config;
2001 };
2002
2003 static bool
2004@@ -104,12 +110,116 @@
2005
2006 }
2007
2008-TEST_F(AndroidDispatcherControllerFdSetup, set_input_focus)
2009-{
2010- using namespace ::testing;
2011-
2012- auto dispatcher = new mtd::MockInputDispatcher(); // We need droidinput::sp
2013- mtd::MockInputConfiguration config;
2014+TEST_F(AndroidDispatcherControllerFdSetup, input_application_opened_behavior)
2015+{
2016+ using namespace ::testing;
2017+
2018+ EXPECT_CALL(config, the_dispatcher()).Times(1)
2019+ .WillOnce(Return(dispatcher));
2020+ mia::DispatcherController controller(mt::fake_shared(config));
2021+
2022+ auto session = std::make_shared<mtd::StubSessionTarget>();
2023+ controller.input_application_opened(session);
2024+ EXPECT_THROW({
2025+ // An application can not be opened twice!
2026+ controller.input_application_opened(session);
2027+ }, std::logic_error);
2028+}
2029+
2030+TEST_F(AndroidDispatcherControllerFdSetup, input_application_closed_behavior)
2031+{
2032+ using namespace ::testing;
2033+
2034+ EXPECT_CALL(config, the_dispatcher()).Times(1)
2035+ .WillOnce(Return(dispatcher));
2036+ mia::DispatcherController controller(mt::fake_shared(config));
2037+
2038+ auto session = std::make_shared<mtd::StubSessionTarget>();
2039+ EXPECT_THROW({
2040+ // We can't close an application which is not open
2041+ controller.input_application_closed(session);
2042+ }, std::logic_error);
2043+ controller.input_application_opened(session);
2044+ controller.input_application_closed(session);
2045+ EXPECT_THROW({
2046+ // Nor can we close an application twice
2047+ controller.input_application_closed(session);
2048+ }, std::logic_error);
2049+}
2050+
2051+TEST_F(AndroidDispatcherControllerFdSetup, input_surface_opened_behavior)
2052+{
2053+ using namespace ::testing;
2054+
2055+ auto session = std::make_shared<mtd::StubSessionTarget>();
2056+ auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
2057+
2058+ EXPECT_CALL(config, the_dispatcher()).Times(1)
2059+ .WillOnce(Return(dispatcher));
2060+ EXPECT_CALL(*dispatcher, registerInputChannel(_, WindowHandleFor(session, surface), false)).Times(1)
2061+ .WillOnce(Return(droidinput::OK));
2062+
2063+ mia::DispatcherController controller(mt::fake_shared(config));
2064+
2065+ EXPECT_THROW({
2066+ // We can't open a surface with an unopened session!
2067+ controller.input_surface_opened(session, surface);
2068+ }, std::logic_error);
2069+ controller.input_application_opened(session);
2070+ controller.input_surface_opened(session, surface);
2071+ EXPECT_THROW({
2072+ // We can't open a surface twice
2073+ controller.input_surface_opened(session, surface);
2074+ }, std::logic_error);
2075+}
2076+
2077+TEST_F(AndroidDispatcherControllerFdSetup, input_surface_closed_behavior)
2078+{
2079+ using namespace ::testing;
2080+
2081+ auto session = std::make_shared<mtd::StubSessionTarget>();
2082+ auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
2083+
2084+ EXPECT_CALL(config, the_dispatcher()).Times(1)
2085+ .WillOnce(Return(dispatcher));
2086+ EXPECT_CALL(*dispatcher, registerInputChannel(_, WindowHandleFor(session, surface), false)).Times(1)
2087+ .WillOnce(Return(droidinput::OK));
2088+ EXPECT_CALL(*dispatcher, unregisterInputChannel(_)).Times(1);
2089+ mia::DispatcherController controller(mt::fake_shared(config));
2090+
2091+ controller.input_application_opened(session);
2092+
2093+ EXPECT_THROW({
2094+ // We can't close a surface which hasn't been opened
2095+ controller.input_surface_closed(surface);
2096+ }, std::logic_error);
2097+ controller.input_surface_opened(session, surface);
2098+ controller.input_surface_closed(surface);
2099+ EXPECT_THROW({
2100+ // Nor can we close a surface twice
2101+ controller.input_surface_closed(surface);
2102+ }, std::logic_error);
2103+}
2104+
2105+TEST_F(AndroidDispatcherControllerFdSetup, on_focus_cleared)
2106+{
2107+ using namespace ::testing;
2108+
2109+ EXPECT_CALL(config, the_dispatcher()).Times(1)
2110+ .WillOnce(Return(dispatcher));
2111+
2112+ EXPECT_CALL(*dispatcher, setFocusedApplication(droidinput::sp<droidinput::InputApplicationHandle>(0))).Times(1);
2113+ EXPECT_CALL(*dispatcher, setInputWindows(EmptyVector())).Times(1);
2114+
2115+ mia::DispatcherController controller(mt::fake_shared(config));
2116+
2117+ controller.focus_cleared();
2118+}
2119+
2120+TEST_F(AndroidDispatcherControllerFdSetup, on_focus_changed)
2121+{
2122+ using namespace ::testing;
2123+
2124 EXPECT_CALL(config, the_dispatcher()).Times(1)
2125 .WillOnce(Return(dispatcher));
2126
2127@@ -119,15 +229,30 @@
2128 {
2129 InSequence seq;
2130 EXPECT_CALL(*dispatcher, setFocusedApplication(ApplicationHandleFor(session))).Times(1);
2131- EXPECT_CALL(*dispatcher, registerInputChannel(_, WindowHandleFor(session, surface), false)).Times(1)
2132- .WillOnce(Return(droidinput::OK));
2133 EXPECT_CALL(*dispatcher, setInputWindows(VectorContainingWindowHandleFor(session, surface))).Times(1);
2134- EXPECT_CALL(*dispatcher, unregisterInputChannel(_)).Times(1);
2135- EXPECT_CALL(*dispatcher, setInputWindows(EmptyVector())).Times(1);
2136 }
2137
2138 mia::DispatcherController controller(mt::fake_shared(config));
2139-
2140- controller.set_input_focus_to(session, surface);
2141- controller.set_input_focus_to(session, std::shared_ptr<mi::SurfaceTarget>());
2142+
2143+ controller.input_application_opened(session);
2144+ controller.input_surface_opened(session, surface);
2145+
2146+ controller.focus_changed(surface);
2147+}
2148+
2149+TEST_F(AndroidDispatcherControllerFdSetup, on_focus_changed_throw_behavior)
2150+{
2151+ using namespace ::testing;
2152+
2153+ EXPECT_CALL(config, the_dispatcher()).Times(1)
2154+ .WillOnce(Return(dispatcher));
2155+
2156+ auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
2157+
2158+ mia::DispatcherController controller(mt::fake_shared(config));
2159+
2160+ EXPECT_THROW({
2161+ // We can't focus surfaces which never opened
2162+ controller.focus_changed(surface);
2163+ }, std::logic_error);
2164 }
2165
2166=== modified file 'tests/unit-tests/input/android/test_android_input_window_handle.cpp'
2167--- tests/unit-tests/input/android/test_android_input_window_handle.cpp 2013-04-04 11:26:58 +0000
2168+++ tests/unit-tests/input/android/test_android_input_window_handle.cpp 2013-04-22 21:32:25 +0000
2169@@ -52,6 +52,7 @@
2170 struct MockSurfaceTarget : public mi::SurfaceTarget
2171 {
2172 MOCK_CONST_METHOD0(server_input_fd, int());
2173+ MOCK_CONST_METHOD0(top_left, geom::Point());
2174 MOCK_CONST_METHOD0(size, geom::Size());
2175 MOCK_CONST_METHOD0(name, std::string());
2176 };
2177@@ -64,6 +65,7 @@
2178
2179 geom::Size const default_surface_size = geom::Size{geom::Width{256},
2180 geom::Height{256}};
2181+ geom::Point const default_surface_top_left = geom::Point{geom::X{10}, geom::Y{10}};
2182 std::string const testing_surface_name = "Test";
2183
2184 // We need a real open fd, as InputWindowHandle's constructor will fcntl() it, and
2185@@ -81,6 +83,8 @@
2186 // for touch/pointer events we will need a position
2187 EXPECT_CALL(surface, size()).Times(1)
2188 .WillOnce(Return(default_surface_size));
2189+ EXPECT_CALL(surface, top_left()).Times(1)
2190+ .WillOnce(Return(default_surface_top_left));
2191 EXPECT_CALL(surface, name()).Times(1)
2192 .WillOnce(Return(testing_surface_name));
2193
2194@@ -93,8 +97,15 @@
2195
2196 EXPECT_EQ(testing_server_fd, info->inputChannel->getFd());
2197
2198+ EXPECT_EQ(default_surface_top_left.x.as_uint32_t(), (uint32_t)(info->frameLeft));
2199+ EXPECT_EQ(default_surface_top_left.y.as_uint32_t(), (uint32_t)(info->frameTop));
2200 EXPECT_EQ(default_surface_size.height.as_uint32_t(), (uint32_t)(info->frameRight - info->frameLeft));
2201 EXPECT_EQ(default_surface_size.height.as_uint32_t(), (uint32_t)(info->frameBottom - info->frameTop));
2202
2203+ EXPECT_EQ(info->frameLeft, info->touchableRegionLeft);
2204+ EXPECT_EQ(info->frameTop, info->touchableRegionTop);
2205+ EXPECT_EQ(info->frameRight, info->touchableRegionRight);
2206+ EXPECT_EQ(info->frameBottom, info->touchableRegionBottom);
2207+
2208 free(filename);
2209 }
2210
2211=== modified file 'tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp'
2212--- tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp 2013-03-22 16:41:59 +0000
2213+++ tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp 2013-04-22 21:32:25 +0000
2214@@ -32,12 +32,12 @@
2215 namespace mt = mir::test;
2216 namespace mtd = mir::test::doubles;
2217
2218-TEST(EventFilterDispatcherPolicy, offers_events_to_filter)
2219+TEST(EventFilterDispatcherPolicy, offers_key_events_to_filter)
2220 {
2221 using namespace ::testing;
2222 droidinput::KeyEvent ev;
2223 mtd::MockEventFilter filter;
2224- mia::EventFilterDispatcherPolicy policy(mt::fake_shared(filter));
2225+ mia::EventFilterDispatcherPolicy policy(mt::fake_shared(filter), true);
2226 uint32_t policy_flags;
2227
2228 EXPECT_CALL(filter, handles(_)).Times(1).WillOnce(Return(false));
2229@@ -53,3 +53,16 @@
2230 EXPECT_TRUE(policy.filterInputEvent(&ev, 0));
2231 }
2232
2233+TEST(EventFilterDispatcherPolicy, motion_events_are_allowed_to_pass_to_clients)
2234+{
2235+ using namespace ::testing;
2236+
2237+ mtd::MockEventFilter filter;
2238+ mia::EventFilterDispatcherPolicy policy(mt::fake_shared(filter), true);
2239+
2240+ uint32_t policy_flags;
2241+ policy.interceptMotionBeforeQueueing(0, policy_flags);
2242+
2243+ // All motion events are allowed. Of course they could later be removed by the input filter.
2244+ EXPECT_TRUE(policy_flags & droidinput::POLICY_FLAG_PASS_TO_USER);
2245+}
2246
2247=== modified file 'tests/unit-tests/shell/test_application_session.cpp'
2248--- tests/unit-tests/shell/test_application_session.cpp 2013-04-17 18:18:31 +0000
2249+++ tests/unit-tests/shell/test_application_session.cpp 2013-04-22 21:32:25 +0000
2250@@ -22,6 +22,7 @@
2251 #include "mir_test/fake_shared.h"
2252 #include "mir_test_doubles/mock_surface_factory.h"
2253 #include "mir_test_doubles/mock_surface.h"
2254+#include "mir_test_doubles/stub_input_target_listener.h"
2255 #include "mir_test_doubles/stub_surface_builder.h"
2256 #include "mir_test_doubles/stub_surface.h"
2257
2258@@ -51,7 +52,8 @@
2259 EXPECT_CALL(surface_factory, create_surface(_));
2260 EXPECT_CALL(*mock_surface, destroy());
2261
2262- msh::ApplicationSession session(mt::fake_shared(surface_factory), "Foo");
2263+ mtd::StubInputTargetListener input_listener;
2264+ msh::ApplicationSession session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
2265
2266 mf::SurfaceCreationParameters params;
2267 auto surf = session.create_surface(params);
2268@@ -75,7 +77,8 @@
2269 .WillOnce(Return(std::make_shared<NiceMock<mtd::MockSurface>>(mt::fake_shared(surface_builder))));
2270 }
2271
2272- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
2273+ mtd::StubInputTargetListener input_listener;
2274+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
2275
2276 mf::SurfaceCreationParameters params;
2277 auto id1 = app_session.create_surface(params);
2278@@ -105,7 +108,8 @@
2279 mtd::MockSurfaceFactory surface_factory;
2280 ON_CALL(surface_factory, create_surface(_)).WillByDefault(Return(mock_surface));
2281
2282- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
2283+ mtd::StubInputTargetListener input_listener;
2284+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
2285
2286 EXPECT_CALL(surface_factory, create_surface(_));
2287
2288@@ -130,7 +134,8 @@
2289 using namespace ::testing;
2290
2291 mtd::MockSurfaceFactory surface_factory;
2292- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
2293+ mtd::StubInputTargetListener input_listener;
2294+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
2295 mf::SurfaceId invalid_surface_id(1);
2296
2297 EXPECT_THROW({
2298@@ -143,7 +148,8 @@
2299 using namespace ::testing;
2300
2301 mtd::MockSurfaceFactory surface_factory;
2302- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
2303+ mtd::StubInputTargetListener input_listener;
2304+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
2305 mf::SurfaceId invalid_surface_id(1);
2306
2307 EXPECT_THROW({
2308
2309=== modified file 'tests/unit-tests/shell/test_registration_order_focus_sequence.cpp'
2310--- tests/unit-tests/shell/test_registration_order_focus_sequence.cpp 2013-04-18 00:00:55 +0000
2311+++ tests/unit-tests/shell/test_registration_order_focus_sequence.cpp 2013-04-22 21:32:25 +0000
2312@@ -22,8 +22,11 @@
2313 #include "mir/shell/registration_order_focus_sequence.h"
2314 #include "mir/frontend/surface_creation_parameters.h"
2315 #include "mir/surfaces/surface.h"
2316+
2317 #include "mir_test_doubles/mock_buffer_bundle.h"
2318 #include "mir_test_doubles/mock_surface_factory.h"
2319+#include "mir_test_doubles/stub_input_target_listener.h"
2320+#include "mir_test/fake_shared.h"
2321
2322 #include <gmock/gmock.h>
2323 #include <gtest/gtest.h>
2324@@ -32,7 +35,8 @@
2325 namespace mc = mir::compositor;
2326 namespace msh = mir::shell;
2327 namespace ms = mir::surfaces;
2328-namespace mtd = mir::test::doubles;
2329+namespace mt = mir::test;
2330+namespace mtd = mt::doubles;
2331
2332 namespace
2333 {
2334@@ -45,6 +49,7 @@
2335 }
2336 std::shared_ptr<mtd::MockSurfaceFactory> factory;
2337 std::shared_ptr<msh::DefaultSessionContainer> container;
2338+ mtd::StubInputTargetListener input_listener;
2339
2340 static std::string const testing_app_name1;
2341 static std::string const testing_app_name2;
2342@@ -60,9 +65,9 @@
2343 {
2344 using namespace ::testing;
2345
2346- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
2347- auto app2 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name2);
2348- auto app3 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name3);
2349+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
2350+ auto app2 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name2);
2351+ auto app3 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name3);
2352
2353 container->insert_session(app1);
2354 container->insert_session(app2);
2355@@ -78,9 +83,9 @@
2356 {
2357 using namespace ::testing;
2358
2359- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
2360- auto app2 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name2);
2361- auto app3 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name3);
2362+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
2363+ auto app2 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name2);
2364+ auto app3 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name3);
2365 container->insert_session(app1);
2366 container->insert_session(app2);
2367 container->insert_session(app3);
2368@@ -95,7 +100,7 @@
2369 {
2370 using namespace ::testing;
2371
2372- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
2373+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
2374 container->insert_session(app1);
2375
2376 msh::RegistrationOrderFocusSequence focus_sequence(container);
2377@@ -107,8 +112,8 @@
2378 {
2379 using namespace ::testing;
2380
2381- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
2382- auto app2 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name2);
2383+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
2384+ auto app2 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name2);
2385 auto null_session = std::shared_ptr<msh::ApplicationSession>();
2386
2387 msh::RegistrationOrderFocusSequence focus_sequence(container);
2388@@ -124,7 +129,7 @@
2389 {
2390 using namespace ::testing;
2391
2392- auto invalid_session = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
2393+ auto invalid_session = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
2394 auto null_session = std::shared_ptr<msh::ApplicationSession>();
2395
2396 msh::RegistrationOrderFocusSequence focus_sequence(container);
2397
2398=== modified file 'tests/unit-tests/shell/test_session_manager.cpp'
2399--- tests/unit-tests/shell/test_session_manager.cpp 2013-04-18 22:29:24 +0000
2400+++ tests/unit-tests/shell/test_session_manager.cpp 2013-04-22 21:32:25 +0000
2401@@ -21,15 +21,19 @@
2402 #include "mir/shell/session_manager.h"
2403 #include "mir/shell/default_session_container.h"
2404 #include "mir/shell/session.h"
2405+#include "mir/shell/input_target_listener.h"
2406 #include "mir/frontend/surface_creation_parameters.h"
2407 #include "mir/surfaces/surface.h"
2408 #include "mir/input/input_channel.h"
2409+
2410+#include "mir_test/fake_shared.h"
2411 #include "mir_test_doubles/mock_buffer_bundle.h"
2412-#include "mir_test/fake_shared.h"
2413 #include "mir_test_doubles/mock_surface_factory.h"
2414 #include "mir_test_doubles/mock_focus_setter.h"
2415 #include "mir_test_doubles/null_buffer_bundle.h"
2416 #include "mir_test_doubles/stub_surface_builder.h"
2417+#include "mir_test_doubles/stub_input_target_listener.h"
2418+#include "mir_test_doubles/mock_input_target_listener.h"
2419
2420 #include "mir/shell/surface.h"
2421
2422@@ -56,7 +60,7 @@
2423 ~MockSessionContainer() noexcept {}
2424 };
2425
2426-struct MockFocusSequence: public msh::FocusSequence
2427+struct MockFocusSequence : public msh::FocusSequence
2428 {
2429 MOCK_CONST_METHOD1(successor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
2430 MOCK_CONST_METHOD1(predecessor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
2431@@ -68,16 +72,18 @@
2432 SessionManagerSetup()
2433 : session_manager(mt::fake_shared(surface_factory),
2434 mt::fake_shared(container),
2435- mt::fake_shared(sequence),
2436- mt::fake_shared(focus_setter))
2437+ mt::fake_shared(focus_sequence),
2438+ mt::fake_shared(focus_setter),
2439+ mt::fake_shared(input_target_listener))
2440 {
2441 }
2442
2443 mtd::StubSurfaceBuilder surface_builder;
2444 mtd::MockSurfaceFactory surface_factory;
2445 testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
2446- MockFocusSequence sequence;
2447+ MockFocusSequence focus_sequence;
2448 testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
2449+ mtd::StubInputTargetListener input_target_listener;
2450
2451 msh::SessionManager session_manager;
2452 };
2453@@ -93,7 +99,7 @@
2454 EXPECT_CALL(focus_setter, set_focus_to(_));
2455 EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<msh::Session>())).Times(1);
2456
2457- EXPECT_CALL(sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
2458+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
2459
2460 auto session = session_manager.open_session("Visual Basic Studio");
2461 session_manager.close_session(session);
2462@@ -118,7 +124,7 @@
2463 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(1);
2464 EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<msh::Session>())).Times(1);
2465
2466- EXPECT_CALL(sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
2467+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
2468
2469 auto session = session_manager.open_session("Visual Basic Studio");
2470 session->create_surface(mf::a_surface().of_size(geom::Size{geom::Width{1024}, geom::Height{768}}));
2471@@ -164,7 +170,7 @@
2472 session_manager.tag_session_with_lightdm_id(session1, 1);
2473 session_manager.focus_session_with_lightdm_id(1);
2474
2475- EXPECT_CALL(sequence, default_focus()).WillOnce(Return(shell_session2));
2476+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return(shell_session2));
2477 EXPECT_CALL(focus_setter, set_focus_to(Eq(shell_session2)));
2478
2479 session_manager.close_session(session1);
2480@@ -193,3 +199,61 @@
2481 session_manager.create_surface_for(session1, mf::a_surface());
2482 }
2483
2484+namespace
2485+{
2486+
2487+struct SessionManagerInputTargetListenerSetup : public testing::Test
2488+{
2489+ SessionManagerInputTargetListenerSetup()
2490+ : session_manager(mt::fake_shared(surface_factory),
2491+ mt::fake_shared(container),
2492+ mt::fake_shared(focus_sequence),
2493+ mt::fake_shared(focus_setter),
2494+ mt::fake_shared(input_target_listener))
2495+ {
2496+ }
2497+
2498+ mtd::StubSurfaceBuilder surface_builder;
2499+ mtd::MockSurfaceFactory surface_factory;
2500+ testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
2501+ testing::NiceMock<MockFocusSequence> focus_sequence;
2502+ testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
2503+ mtd::MockInputTargetListener input_target_listener;
2504+
2505+ msh::SessionManager session_manager;
2506+};
2507+
2508+}
2509+
2510+TEST_F(SessionManagerInputTargetListenerSetup, listener_is_notified_of_session_and_surfacelifecycle)
2511+{
2512+ using namespace ::testing;
2513+
2514+ std::shared_ptr<mi::InputChannel> null_input_channel;
2515+ ON_CALL(surface_factory, create_surface(_)).WillByDefault(
2516+ Return(std::make_shared<msh::Surface>(
2517+ mt::fake_shared(surface_builder),
2518+ mf::a_surface(),
2519+ null_input_channel)));
2520+
2521+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
2522+ {
2523+ InSequence seq;
2524+
2525+ EXPECT_CALL(input_target_listener, input_application_opened(_))
2526+ .Times(1);
2527+ EXPECT_CALL(input_target_listener, input_surface_opened(_, _)).Times(1);
2528+ EXPECT_CALL(input_target_listener, focus_changed(_)).Times(1);
2529+ EXPECT_CALL(input_target_listener, input_surface_closed(_)).Times(1);
2530+ EXPECT_CALL(input_target_listener, input_application_closed(_))
2531+ .Times(1);
2532+ EXPECT_CALL(input_target_listener, focus_cleared()).Times(1);
2533+ }
2534+
2535+ {
2536+ auto session = session_manager.open_session("test");
2537+ auto surf = session_manager.create_surface_for(session, mf::a_surface());
2538+ session->destroy_surface(surf);
2539+ session_manager.close_session(session);
2540+ }
2541+}
2542
2543=== modified file 'tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp'
2544--- tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp 2013-04-19 15:33:04 +0000
2545+++ tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp 2013-04-22 21:32:25 +0000
2546@@ -27,7 +27,6 @@
2547 #include "mir_test_doubles/mock_buffer_bundle.h"
2548 #include "mir_test/fake_shared.h"
2549 #include "mir_test_doubles/mock_surface_factory.h"
2550-#include "mir_test_doubles/mock_input_focus_selector.h"
2551 #include "mir_test_doubles/stub_surface.h"
2552 #include "mir_test_doubles/mock_surface.h"
2553 #include "mir_test_doubles/stub_surface_builder.h"
2554@@ -64,8 +63,6 @@
2555 {
2556 using namespace ::testing;
2557
2558- NiceMock<mtd::MockInputFocusSelector> input_focus_selector;
2559-
2560 NiceMock<MockShellSession> app1, app2, app3;
2561 msh::DefaultSessionContainer model;
2562
2563@@ -73,7 +70,7 @@
2564 ON_CALL(app2, default_surface()).WillByDefault(Return(std::shared_ptr<msh::Surface>()));
2565 ON_CALL(app3, default_surface()).WillByDefault(Return(std::shared_ptr<msh::Surface>()));
2566
2567- msh::SingleVisibilityFocusMechanism focus_mechanism(mt::fake_shared(model), mt::fake_shared(input_focus_selector));
2568+ msh::SingleVisibilityFocusMechanism focus_mechanism(mt::fake_shared(model));
2569
2570 EXPECT_CALL(app1, show()).Times(1);
2571 EXPECT_CALL(app2, hide()).Times(1);
2572@@ -89,23 +86,3 @@
2573
2574 focus_mechanism.set_focus_to(mt::fake_shared(app1));
2575 }
2576-
2577-TEST(SingleVisibilityFocusMechanism, mechanism_sets_input_focus_from_default_surface)
2578-{
2579- using namespace ::testing;
2580-
2581- mtd::MockInputFocusSelector input_focus_selector;
2582- msh::DefaultSessionContainer model;
2583- auto session = std::make_shared<NiceMock<MockShellSession>>();
2584- auto surface = std::make_shared<mtd::MockSurface>(std::make_shared<mtd::StubSurfaceBuilder>());
2585-
2586- msh::SingleVisibilityFocusMechanism focus_mechanism(mt::fake_shared(model), mt::fake_shared(input_focus_selector));
2587-
2588- EXPECT_CALL(*session, default_surface()).Times(1).WillOnce(Return(surface));
2589-
2590- EXPECT_CALL(input_focus_selector, set_input_focus_to(Eq(session), Eq(surface))).Times(1);
2591-
2592- model.insert_session(session);
2593- focus_mechanism.set_focus_to(session);
2594-}
2595-
2596
2597=== modified file 'tests/unit-tests/shell/test_surface.cpp'
2598--- tests/unit-tests/shell/test_surface.cpp 2013-04-16 17:42:26 +0000
2599+++ tests/unit-tests/shell/test_surface.cpp 2013-04-22 21:32:25 +0000
2600@@ -220,6 +220,24 @@
2601 }, std::runtime_error);
2602 }
2603
2604+TEST_F(ShellSurface, top_left_throw_behavior)
2605+{
2606+ msh::Surface test(
2607+ mt::fake_shared(surface_builder),
2608+ mf::a_surface(),
2609+ null_input_channel);
2610+
2611+ EXPECT_NO_THROW({
2612+ test.top_left();
2613+ });
2614+
2615+ surface_builder.reset_surface();
2616+
2617+ EXPECT_THROW({
2618+ test.top_left();
2619+ }, std::runtime_error);
2620+}
2621+
2622 TEST_F(ShellSurface, name_throw_behavior)
2623 {
2624 msh::Surface test(
2625
2626=== modified file 'tests/unit-tests/shell/test_the_session_container_implementation.cpp'
2627--- tests/unit-tests/shell/test_the_session_container_implementation.cpp 2013-04-18 00:00:55 +0000
2628+++ tests/unit-tests/shell/test_the_session_container_implementation.cpp 2013-04-22 21:32:25 +0000
2629@@ -22,6 +22,7 @@
2630 #include "mir/frontend/surface_creation_parameters.h"
2631 #include "mir/surfaces/surface.h"
2632 #include "mir_test_doubles/mock_buffer_bundle.h"
2633+#include "mir_test_doubles/stub_input_target_listener.h"
2634 #include "mir_test_doubles/mock_surface_factory.h"
2635
2636 #include <gmock/gmock.h>
2637@@ -38,8 +39,10 @@
2638 auto factory = std::make_shared<mtd::MockSurfaceFactory>();
2639 msh::DefaultSessionContainer container;
2640
2641- container.insert_session(std::make_shared<msh::ApplicationSession>(factory, "Visual Studio 7"));
2642- container.insert_session(std::make_shared<msh::ApplicationSession>(factory, "Visual Studio 8"));
2643+ container.insert_session(std::make_shared<msh::ApplicationSession>(factory, std::make_shared<mtd::StubInputTargetListener>(),
2644+ "Visual Studio 7"));
2645+ container.insert_session(std::make_shared<msh::ApplicationSession>(factory, std::make_shared<mtd::StubInputTargetListener>(),
2646+ "Visual Studio 8"));
2647
2648 struct local
2649 {
2650@@ -64,8 +67,8 @@
2651 auto factory = std::make_shared<mtd::MockSurfaceFactory>();
2652 msh::DefaultSessionContainer container;
2653
2654- auto session = std::make_shared<msh::ApplicationSession>(factory,
2655- "Visual Studio 7");
2656+ auto session = std::make_shared<msh::ApplicationSession>(factory, std::make_shared<mtd::StubInputTargetListener>(),
2657+ "Visual Studio 7");
2658 EXPECT_THROW({
2659 container.remove_session(session);
2660 }, std::logic_error);

Subscribers

People subscribed via source and target branches