Mir

Merge lp:~robertcarr/mir/rebuild-input-targeting into lp:~mir-team/mir/trunk

Proposed by Robert Carr
Status: Merged
Approved by: Alexandros Frantzis
Approved revision: no longer in the source branch.
Merged at revision: 712
Proposed branch: lp:~robertcarr/mir/rebuild-input-targeting
Merge into: lp:~mir-team/mir/trunk
Diff against target: 6675 lines (+2366/-1515)
89 files modified
3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp (+128/-126)
3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h (+27/-6)
3rd_party/android-input/android/frameworks/base/services/input/InputEnumerator.h (+43/-0)
3rd_party/android-input/android/frameworks/base/services/input/InputManager.h (+0/-109)
examples/render_surfaces.cpp (+0/-1)
include/server/mir/default_server_configuration.h (+10/-8)
include/server/mir/input/input_configuration.h (+18/-21)
include/server/mir/input/input_targets.h (+49/-0)
include/server/mir/input/null_input_configuration.h (+49/-0)
include/server/mir/input/null_input_manager.h (+0/-51)
include/server/mir/input/null_input_target_listener.h (+0/-63)
include/server/mir/input/session_target.h (+0/-45)
include/server/mir/input/surface_target.h (+1/-1)
include/server/mir/shell/application_session.h (+1/-5)
include/server/mir/shell/input_target_listener.h (+0/-59)
include/server/mir/shell/input_targeter.h (+52/-0)
include/server/mir/shell/session.h (+1/-2)
include/server/mir/shell/session_manager.h (+1/-3)
include/server/mir/shell/single_visibility_focus_mechanism.h (+5/-1)
include/server/mir/shell/surface.h (+5/-10)
include/server/mir/shell/surface_source.h (+1/-6)
include/server/mir/surfaces/input_registrar.h (+54/-0)
include/server/mir/surfaces/surface.h (+12/-1)
include/server/mir/surfaces/surface_stack.h (+18/-3)
include/test/mir_test_doubles/mock_input_configuration.h (+5/-0)
include/test/mir_test_doubles/mock_input_dispatcher.h (+4/-1)
include/test/mir_test_doubles/mock_input_registrar.h (+7/-12)
include/test/mir_test_doubles/mock_input_targeter.h (+44/-0)
include/test/mir_test_doubles/mock_surface.h (+2/-1)
include/test/mir_test_doubles/stub_input_registrar.h (+6/-20)
include/test/mir_test_doubles/stub_input_targeter.h (+45/-0)
include/test/mir_test_doubles/stub_session_target.h (+0/-44)
include/test/mir_test_doubles/stub_surface_builder.h (+2/-1)
include/test/mir_test_doubles/stub_surface_target.h (+3/-2)
include/test/mir_test_framework/testing_server_configuration.h (+1/-2)
src/server/default_server_configuration.cpp (+42/-33)
src/server/frontend/session_mediator.cpp (+1/-1)
src/server/input/CMakeLists.txt (+2/-0)
src/server/input/android/CMakeLists.txt (+3/-1)
src/server/input/android/android_input_application_handle.cpp (+6/-6)
src/server/input/android/android_input_application_handle.h (+3/-3)
src/server/input/android/android_input_manager.cpp (+8/-6)
src/server/input/android/android_input_manager.h (+4/-7)
src/server/input/android/android_input_registrar.cpp (+78/-0)
src/server/input/android/android_input_registrar.h (+72/-0)
src/server/input/android/android_input_target_enumerator.cpp (+49/-0)
src/server/input/android/android_input_target_enumerator.h (+67/-0)
src/server/input/android/android_input_targeter.cpp (+26/-77)
src/server/input/android/android_input_targeter.h (+13/-22)
src/server/input/android/android_window_handle_repository.h (+59/-0)
src/server/input/android/default_android_input_configuration.cpp (+49/-1)
src/server/input/android/default_android_input_configuration.h (+35/-13)
src/server/input/null_input_configuration.cpp (+93/-0)
src/server/shell/application_session.cpp (+1/-7)
src/server/shell/session_manager.cpp (+2/-15)
src/server/shell/single_visibility_focus_mechanism.cpp (+16/-4)
src/server/shell/surface.cpp (+38/-15)
src/server/shell/surface_source.cpp (+2/-6)
src/server/surfaces/surface.cpp (+30/-1)
src/server/surfaces/surface_stack.cpp (+25/-3)
src/shared/input/android/android_input_receiver.cpp (+26/-22)
src/shared/input/android/android_input_receiver.h (+2/-0)
tests/acceptance-tests/test_client_input.cpp (+239/-59)
tests/acceptance-tests/test_focus_selection.cpp (+9/-13)
tests/acceptance-tests/test_server_shutdown.cpp (+9/-5)
tests/behavior-tests/session_management_context.cpp (+0/-3)
tests/death-tests/test_application_manager_death.cpp (+0/-1)
tests/integration-tests/graphics/android/test_internal_client.cpp (+6/-2)
tests/integration-tests/input/android/CMakeLists.txt (+0/-1)
tests/integration-tests/input/android/test_android_cursor_listener.cpp (+15/-3)
tests/integration-tests/input/android/test_android_input_manager.cpp (+36/-23)
tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp (+0/-118)
tests/integration-tests/shell/test_session_manager.cpp (+3/-7)
tests/mir_test_framework/testing_server_options.cpp (+7/-19)
tests/unit-tests/input/android/CMakeLists.txt (+2/-1)
tests/unit-tests/input/android/test_android_input_application_handle.cpp (+23/-19)
tests/unit-tests/input/android/test_android_input_manager.cpp (+2/-25)
tests/unit-tests/input/android/test_android_input_registrar.cpp (+25/-169)
tests/unit-tests/input/android/test_android_input_target_enumerator.cpp (+161/-0)
tests/unit-tests/input/android/test_android_input_targeter.cpp (+169/-0)
tests/unit-tests/input/android/test_android_input_window_handle.cpp (+2/-2)
tests/unit-tests/shell/test_application_session.cpp (+5/-11)
tests/unit-tests/shell/test_registration_order_focus_sequence.cpp (+10/-12)
tests/unit-tests/shell/test_session_manager.cpp (+6/-80)
tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp (+41/-2)
tests/unit-tests/shell/test_surface.cpp (+63/-61)
tests/unit-tests/shell/test_the_session_container_implementation.cpp (+3/-5)
tests/unit-tests/surfaces/test_surface.cpp (+76/-19)
tests/unit-tests/surfaces/test_surface_stack.cpp (+108/-8)
To merge this branch: bzr merge lp:~robertcarr/mir/rebuild-input-targeting
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alexandros Frantzis (community) Approve
Robert Ancell Approve
Alan Griffiths Approve
Review via email: mp+165712@code.launchpad.net

Commit message

Rebuild input targeting subsystem to enable multiple surface touch input picking.

Description of the change

This branch is a rework of the interface between the android input stack and Mir.

TestClientInput, multiple_clients_receive_motion_inside_windows, is the acceptance test driving the branch. A scenario where the pointer is dragged across two windows laid out next to one another.

This of course fails in trunk, as the "InputDispatcherController" only supports passing one input window through to the InputDispatcher at a time.

This branch has two major pushes:
1. Enable the droidinput::InputDispatcher to work in terms of an InputEnumerator interface (i.e. the SurfaceStack) rather than through the setInputWindows stack synchronization mechanism.
2. A rebuilding of the Mir/droidinput interface (some bits such as as surface/input registration need to move down to the ms:: layer (from the shell layer).

First, the Mir changes:

InputConfiguration/AndroidInputConfiguration is cleaned up to reduce coupling between the rest of the server and mir::input::android. The interfaces between mir::input:: and the rest of the server are reduced to:

ms::InputRegistrar - Used by the SurfaceStack to register input surfaces and notify the dispatcher of surface destruction.
msh::InputTargeter - Used by the shell to set Keyboard focus.
mi::InputManager - Used by the DisplayServer to start and stop input.
mi::InputTargets/SurfaceTarget - Provided by the surface stack/surface to the InputDispatcher in order to enumerate potential targets for input (i.e. during touch input picking).

The input channel factory is left over, but should be merged with the InputRegistrar in a later branch.

Input channel creation and association is moved from the shell surface to the surface stack itself (at surface creation time).

On the android-input side...

The current design of the droidinput::InputDispatcher interface is based around a setInputWindows interface, which is used to copy the window stack to the InputDispatcher. The InputDispatcher then inspects the window stack to generate events for itself (such as window removed, focus changed, etc). Implementing the stack synchronization for multiple surfaces was looking pretty cumbersome. This interface in general is a little frustrating to work with, and fights against what we want to present to the shell (the ability to arbitrarily target input events).

droidinput::InputDispatcher is reworked to accept an InputEnumerator (provided by the mi::InputTargets through an adapter class..mia::InputTargetEnumerator) and modified to remove it's internal copy of the stack. In some cases the copying of the window stack was used as notification for events (i.e. window removed, key focus changed), these events are split in to new methods.

To post a comment you must log in.
Revision history for this message
Robert Carr (robertcarr) wrote :

Some old test code from before we had a full stack of input tests was deemed as not worth updating to new interfaces, i.e. the dispatcher-check tool and test_fake_event_hub_to_event_filter.

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

Overall, this looks like a nice simplification but there's a lot too it and I've not processed it all yet. Meanwhile...

include/server/mir/input/null_input_configuration.h
include/server/mir/input/null_input_registrar.h
include/server/mir/input/null_input_targeter.h

Too much implementation in a header files

~~~~

1317 + virtual ~NullInputConfiguration() {}

no reason not to be noexcept

~~~~

1777 + friend class SessionManager;

I've yet worked out what really motivates this, but it is probably not the right solution.

~~~~

1923 +

Whitespace

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

- Reorganized NullInputConfiguration (remove public headers for null registrar/targeter/manager, and placed in new null_input_manager.cpp implementation. + default destructor (r750)
- Whitespace fix (r751)
- Removed session manager friend class and internal_surface method through addition of shell::surface::take_input_focus as we discussed on irc

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

There seems to be a lot of "for_each" use that replaces a loop that can exit early. Is this an efficiency concern? Would a for_each_while(std::function<bool(sp<InputWindowHandle> const&)> const& callback) option be useful?

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

Overall, this looks like a nice simplification but there's a lot to it and (due to the poor test coverage of the 3rd_party input code) I don't feel confident that nothing breaks as a result.

It isn't easy to get the code under test (especially without reworking it - which is what this MP does), so I can't insist on "more tests".

Anyway, there's a bit of tidy up needed...

226 + synthesizeCancelationEventsForInputChannelLocked(
227 + focusedInputChannel, options);

Strange indentation

~~~~

2845 + virtual ~InputRegistrar() noexcept(true) {}

2978 + virtual ~InputTargetEnumerator() noexcept(true) {}

These don't gain by being inline

~~~~

2853 +protected:
2854 + InputRegistrar(const InputRegistrar&) = delete;
2855 + InputRegistrar& operator=(const InputRegistrar&) = delete;

2982 +protected:
2983 + InputTargetEnumerator(const InputTargetEnumerator&) = delete;
2984 + InputTargetEnumerator& operator=(const InputTargetEnumerator&) = delete;

No need for a protected section for these - and aren't they deleted in the base anyway?

~~~~~

2858 + droidinput::sp<droidinput::InputDispatcherInterface> input_dispatcher;

should be const

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

Some cleanup!

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

Overall, this looks like a nice simplification.

But there's a lot to it and (due to the poor test coverage of the 3rd_party input code) I don't feel confident that nothing breaks as a result: I'd prefer some more eyes on this before it lands. **HINT**

review: Approve
Revision history for this message
Robert Ancell (robert-ancell) wrote :

I'll lend you some eyes... It's a huge patch and hard to see all the implications but I can't see anything wrong with it.

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

Looks good overall (in a "it's so complicated that there are no obvious deficiencies" way :))

Non-blocking nits (taking into account the size of this MP...):

1334 + NullInputConfiguration(const NullInputConfiguration&) = delete;
1335 + NullInputConfiguration& operator=(const NullInputConfiguration&) = delete;

3175 + InputTargeter(const InputTargeter&) = delete;
3176 + InputTargeter& operator=(const InputTargeter&) = delete;

Not needed.

2759 + std::unique_lock<std::mutex> lock(handles_mutex);

std::lock_guard is supposed to be slightly more lightweight than std::unique_lock, and there is no reason not to prefer lock_guard when condition variables and lock transfers are not involved

4407 + PositionList surface_positions_by_name;
4457 + int screen_width, screen_height;
4458 + PositionList positions;
4492 + MirSurfaceParameters params;

Could be const.

In tests/unit-tests/surfaces/test_surface_stack.cpp:

+ ms::SurfaceStack stack{std::make_shared<StubBufferBundleFactory>(),
+ std::make_shared<StubInputChannelFactory>(),
+ mt::fake_shared(registrar)};

Strange indentation (at various points where the stack is constructed).

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

The trunk its merged!

Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (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
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp'
2--- 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp 2013-05-28 17:52:18 +0000
3+++ 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp 2013-05-30 19:33:26 +0000
4@@ -186,6 +186,12 @@
5 policy->getDispatcherConfiguration(&mConfig);
6 }
7
8+void InputDispatcher::setInputEnumerator(sp<InputEnumerator> const& enumerator)
9+{
10+ AutoMutex _l(mLock);
11+ mEnumerator = enumerator;
12+}
13+
14 InputDispatcher::~InputDispatcher() {
15 { // acquire lock
16 AutoMutex _l(mLock);
17@@ -424,10 +430,8 @@
18 }
19
20 sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
21- // Traverse windows from front to back to find touched window.
22- size_t numWindows = mWindowHandles.size();
23- for (size_t i = 0; i < numWindows; i++) {
24- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
25+ sp<InputWindowHandle> foundHandle = NULL;
26+ mEnumerator->for_each([&](sp<InputWindowHandle> windowHandle) {
27 const InputWindowInfo* windowInfo = windowHandle->getInfo();
28 int32_t flags = windowInfo->layoutParamsFlags;
29
30@@ -437,17 +441,17 @@
31 | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
32 if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
33 // Found window.
34- return windowHandle;
35+ foundHandle = windowHandle;
36 }
37 }
38 }
39
40 if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
41- // Error window is on top but not visible, so touch is dropped.
42- return NULL;
43+ foundHandle = NULL;
44 }
45- }
46- return NULL;
47+ });
48+
49+ return foundHandle;
50 }
51
52 void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
53@@ -1141,14 +1145,14 @@
54 getAxisValue(AMOTION_EVENT_AXIS_X));
55 int32_t y = int32_t(entry->pointerCoords[pointerIndex].
56 getAxisValue(AMOTION_EVENT_AXIS_Y));
57- sp<InputWindowHandle> newTouchedWindowHandle;
58+ sp<InputWindowHandle> newTouchedWindowHandle = NULL;
59 sp<InputWindowHandle> topErrorWindowHandle;
60 bool isTouchModal = false;
61
62 // Traverse windows from front to back to find touched window and outside targets.
63- size_t numWindows = mWindowHandles.size();
64- for (size_t i = 0; i < numWindows; i++) {
65- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
66+ mEnumerator->for_each([&](sp<InputWindowHandle> const& windowHandle){
67+ if (newTouchedWindowHandle != NULL)
68+ return;
69 const InputWindowInfo* windowInfo = windowHandle->getInfo();
70 int32_t flags = windowInfo->layoutParamsFlags;
71
72@@ -1167,7 +1171,7 @@
73 || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) {
74 newTouchedWindowHandle = windowHandle;
75 }
76- break; // found touched window, exit window loop
77+ return; // found touched window, exit window loop
78 }
79 }
80
81@@ -1182,7 +1186,7 @@
82 windowHandle, outsideTargetFlags, BitSet32(0));
83 }
84 }
85- }
86+ });
87
88 // If there is an error window but it is not taking focus (typically because
89 // it is invisible) then wait for it. Any other focused window may in
90@@ -1408,12 +1412,12 @@
91 // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
92 // engine only supports touch events. We would need to add a mechanism similar
93 // to View.onGenericMotionEvent to enable wallpapers to handle these events.
94+ // TODO: What does any of this mean? ~racarr
95 if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
96 sp<InputWindowHandle> foregroundWindowHandle =
97 mTempTouchState.getFirstForegroundWindowHandle();
98 if (foregroundWindowHandle->getInfo()->hasWallpaper) {
99- for (size_t i = 0; i < mWindowHandles.size(); i++) {
100- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
101+ mEnumerator->for_each([&](sp<InputWindowHandle> const& windowHandle){
102 if (windowHandle->getInfo()->layoutParamsType
103 == InputWindowInfo::TYPE_WALLPAPER) {
104 mTempTouchState.addOrUpdateWindow(windowHandle,
105@@ -1421,7 +1425,7 @@
106 | InputTarget::FLAG_DISPATCH_AS_IS,
107 BitSet32(0));
108 }
109- }
110+ });
111 }
112 }
113
114@@ -1586,20 +1590,23 @@
115
116 bool InputDispatcher::isWindowObscuredAtPointLocked(
117 const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
118- size_t numWindows = mWindowHandles.size();
119- for (size_t i = 0; i < numWindows; i++) {
120- sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
121+ bool obscured = false;
122+ bool seen_handle = false;
123+
124+ mEnumerator->for_each([&](sp<InputWindowHandle> const& otherHandle){
125 if (otherHandle == windowHandle) {
126- break;
127+ seen_handle = true;
128+ return;
129 }
130-
131- const InputWindowInfo* otherInfo = otherHandle->getInfo();
132- if (otherInfo->visible && ! otherInfo->isTrustedOverlay()
133+ if (seen_handle) {
134+ const InputWindowInfo* otherInfo = otherHandle->getInfo();
135+ if (otherInfo->visible && ! otherInfo->isTrustedOverlay()
136 && otherInfo->frameContainsPoint(x, y)) {
137- return true;
138+ obscured = true;
139+ }
140 }
141- }
142- return false;
143+ });
144+ return obscured;
145 }
146
147 bool InputDispatcher::isWindowReadyForMoreInputLocked(nsecs_t currentTime,
148@@ -2665,79 +2672,74 @@
149
150 sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
151 const sp<InputChannel>& inputChannel) const {
152- size_t numWindows = mWindowHandles.size();
153- for (size_t i = 0; i < numWindows; i++) {
154- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
155+ sp<InputWindowHandle> foundHandle = NULL;
156+ mEnumerator->for_each([&](sp<InputWindowHandle> const& windowHandle){
157 if (windowHandle->getInputChannel() == inputChannel) {
158- return windowHandle;
159+ foundHandle = windowHandle;
160 }
161- }
162- return NULL;
163+ });
164+ return foundHandle;
165 }
166
167 bool InputDispatcher::hasWindowHandleLocked(
168 const sp<InputWindowHandle>& windowHandle) const {
169- size_t numWindows = mWindowHandles.size();
170- for (size_t i = 0; i < numWindows; i++) {
171- if (mWindowHandles.itemAt(i) == windowHandle) {
172- return true;
173- }
174- }
175- return false;
176-}
177-
178-void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
179-#if DEBUG_FOCUS
180- ALOGD("setInputWindows");
181+ bool found_handle = false;
182+ mEnumerator->for_each([&](sp<InputWindowHandle> const& otherHandle){
183+ if (otherHandle == windowHandle) {
184+ found_handle = true;
185+ }
186+ });
187+ return found_handle;
188+}
189+
190+void InputDispatcher::setKeyboardFocus(const sp<InputWindowHandle>& newFocusedWindowHandle)
191+{
192+#if DEBUG_FOCUS
193+ ALOGD("setKeyboardFocus");
194+#endif
195+ {
196+ AutoMutex _l(mLock);
197+ setKeyboardFocusLocked(newFocusedWindowHandle);
198+ }
199+ mLooper->wake();
200+}
201+
202+void InputDispatcher::setKeyboardFocusLocked(const sp<InputWindowHandle>& newFocusedWindowHandle)
203+{
204+ if (mFocusedWindowHandle != newFocusedWindowHandle) {
205+ if (mFocusedWindowHandle != NULL) {
206+#if DEBUG_FOCUS
207+ ALOGD("Focus left window: %s",
208+ c_str(mFocusedWindowHandle->getName()));
209+#endif
210+ sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
211+ if (focusedInputChannel != NULL) {
212+ CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
213+ "focus left window");
214+ synthesizeCancelationEventsForInputChannelLocked(
215+ focusedInputChannel, options);
216+ }
217+ }
218+ if (newFocusedWindowHandle != NULL) {
219+#if DEBUG_FOCUS
220+ ALOGD("Focus entered window: %s",
221+ c_str(newFocusedWindowHandle->getName()));
222+#endif
223+ }
224+ mFocusedWindowHandle = newFocusedWindowHandle;
225+ }
226+}
227+
228+void InputDispatcher::notifyWindowRemoved(const sp<InputWindowHandle>& windowHandle)
229+{
230+#if DEBUG_FOCUS
231+ ALOGD("notifyWindowRemoved");
232 #endif
233 { // acquire lock
234 AutoMutex _l(mLock);
235
236- Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
237- mWindowHandles = inputWindowHandles;
238-
239- sp<InputWindowHandle> newFocusedWindowHandle;
240- bool foundHoveredWindow = false;
241- for (size_t i = 0; i < mWindowHandles.size(); i++) {
242- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
243- if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) {
244- mWindowHandles.removeAt(i--);
245- continue;
246- }
247- if (windowHandle->getInfo()->hasFocus) {
248- newFocusedWindowHandle = windowHandle;
249- }
250- if (windowHandle == mLastHoverWindowHandle) {
251- foundHoveredWindow = true;
252- }
253- }
254-
255- if (!foundHoveredWindow) {
256+ if (windowHandle == mLastHoverWindowHandle)
257 mLastHoverWindowHandle = NULL;
258- }
259-
260- if (mFocusedWindowHandle != newFocusedWindowHandle) {
261- if (mFocusedWindowHandle != NULL) {
262-#if DEBUG_FOCUS
263- ALOGD("Focus left window: %s",
264- c_str(mFocusedWindowHandle->getName()));
265-#endif
266- sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
267- if (focusedInputChannel != NULL) {
268- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
269- "focus left window");
270- synthesizeCancelationEventsForInputChannelLocked(
271- focusedInputChannel, options);
272- }
273- }
274- if (newFocusedWindowHandle != NULL) {
275-#if DEBUG_FOCUS
276- ALOGD("Focus entered window: %s",
277- c_str(newFocusedWindowHandle->getName()));
278-#endif
279- }
280- mFocusedWindowHandle = newFocusedWindowHandle;
281- }
282
283 for (size_t i = 0; i < mTouchState.windows.size(); i++) {
284 TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
285@@ -2750,20 +2752,21 @@
286 touchedWindow.windowHandle->getInputChannel();
287 if (touchedInputChannel != NULL) {
288 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
289- "touched window was removed");
290+ "touched window was removed");
291 synthesizeCancelationEventsForInputChannelLocked(
292- touchedInputChannel, options);
293+ touchedInputChannel, options);
294 }
295 mTouchState.windows.removeAt(i--);
296 }
297 }
298
299+ if (windowHandle == mFocusedWindowHandle)
300+ setKeyboardFocusLocked(NULL);
301+
302 } // release lock
303-
304- // Wake up poll loop since it may need to make new input dispatching choices.
305 mLooper->wake();
306 }
307-
308+
309 void InputDispatcher::setFocusedApplication(
310 const sp<InputApplicationHandle>& inputApplicationHandle) {
311 #if DEBUG_FOCUS
312@@ -2800,6 +2803,9 @@
313 ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
314 #endif
315
316+ if (enabled)
317+ assert(mEnumerator != NULL);
318+
319 bool changed;
320 { // acquire lock
321 AutoMutex _l(mLock);
322@@ -2988,37 +2994,33 @@
323 dump.append(INDENT "TouchedWindows: <none>\n");
324 }
325
326- if (!mWindowHandles.isEmpty()) {
327- dump.append(INDENT "Windows:\n");
328- for (size_t i = 0; i < mWindowHandles.size(); i++) {
329- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
330- const InputWindowInfo* windowInfo = windowHandle->getInfo();
331-
332- appendFormat(dump, INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
333- "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
334- "frame=[%d,%d][%d,%d], scale=%f, "
335- "touchableRegion=[%d,%d][%d,%d]",
336- i, c_str(windowInfo->name),
337- toString(windowInfo->paused),
338- toString(windowInfo->hasFocus),
339- toString(windowInfo->hasWallpaper),
340- toString(windowInfo->visible),
341- toString(windowInfo->canReceiveKeys),
342- windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
343- windowInfo->layer,
344- windowInfo->frameLeft, windowInfo->frameTop,
345- windowInfo->frameRight, windowInfo->frameBottom,
346- windowInfo->scaleFactor,
347- windowInfo->touchableRegionLeft, windowInfo->touchableRegionTop,
348- windowInfo->touchableRegionRight, windowInfo->touchableRegionBottom);
349- appendFormat(dump, ", inputFeatures=0x%08x", windowInfo->inputFeatures);
350- appendFormat(dump, ", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
351- windowInfo->ownerPid, windowInfo->ownerUid,
352- windowInfo->dispatchingTimeout / 1000000.0);
353- }
354- } else {
355- dump.append(INDENT "Windows: <none>\n");
356- }
357+ dump.append(INDENT "Windows:\n");
358+
359+ mEnumerator->for_each([&](sp<InputWindowHandle> const& windowHandle){
360+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
361+
362+ appendFormat(dump, INDENT2 "name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
363+ "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
364+ "frame=[%d,%d][%d,%d], scale=%f, "
365+ "touchableRegion=[%d,%d][%d,%d]",
366+ c_str(windowInfo->name),
367+ toString(windowInfo->paused),
368+ toString(windowInfo->hasFocus),
369+ toString(windowInfo->hasWallpaper),
370+ toString(windowInfo->visible),
371+ toString(windowInfo->canReceiveKeys),
372+ windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
373+ windowInfo->layer,
374+ windowInfo->frameLeft, windowInfo->frameTop,
375+ windowInfo->frameRight, windowInfo->frameBottom,
376+ windowInfo->scaleFactor,
377+ windowInfo->touchableRegionLeft, windowInfo->touchableRegionTop,
378+ windowInfo->touchableRegionRight, windowInfo->touchableRegionBottom);
379+ appendFormat(dump, ", inputFeatures=0x%08x", windowInfo->inputFeatures);
380+ appendFormat(dump, ", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
381+ windowInfo->ownerPid, windowInfo->ownerUid,
382+ windowInfo->dispatchingTimeout / 1000000.0);
383+ });
384
385 if (!mMonitoringChannels.isEmpty()) {
386 dump.append(INDENT "MonitoringChannels:\n");
387
388=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h'
389--- 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h 2013-05-28 17:47:03 +0000
390+++ 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h 2013-05-30 19:33:26 +0000
391@@ -38,6 +38,7 @@
392 #include "InputWindow.h"
393 #include "InputApplication.h"
394 #include "InputListener.h"
395+#include "InputEnumerator.h"
396
397 #include <memory>
398
399@@ -283,6 +284,13 @@
400 virtual ~InputDispatcherInterface() { }
401
402 public:
403+ /*
404+ * Sets the enumerator of input targets. This must be called prior to enabling input dispatch.
405+ *
406+ * This method may be called by any thread.
407+ */
408+ virtual void setInputEnumerator(sp<InputEnumerator> const& enumerator) = 0;
409+
410 /* Dumps the state of the input dispatcher.
411 *
412 * This method may be called on any thread (usually by the input manager). */
413@@ -309,11 +317,18 @@
414 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
415 uint32_t policyFlags) = 0;
416
417- /* Sets the list of input windows.
418+ /*
419+ * Sets the keyboard focus target.
420 *
421- * This method may be called on any thread (usually by the input manager).
422- */
423- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
424+ * This method may be called on any thread.
425+ */
426+ virtual void setKeyboardFocus(const sp<InputWindowHandle>& windowHandle) = 0;
427+ /*
428+ * Notify that a window handle is about to vanish
429+
430+ * This method may be called on any thread.
431+ */
432+ virtual void notifyWindowRemoved(const sp<InputWindowHandle>& windowHandle) = 0;
433
434 /* Sets the focused application.
435 *
436@@ -378,6 +393,8 @@
437 public:
438 explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy, std::shared_ptr<mir::input::InputReport> const& input_report);
439
440+ virtual void setInputEnumerator(sp<InputEnumerator> const& enumerator);
441+
442 virtual void dump(String8& dump);
443 virtual void monitor();
444
445@@ -393,7 +410,9 @@
446 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
447 uint32_t policyFlags);
448
449- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
450+ virtual void setKeyboardFocus(const sp<InputWindowHandle>& windowHandle);
451+ virtual void notifyWindowRemoved(const sp<InputWindowHandle>& windowHandle);
452+
453 virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
454 virtual void setInputDispatchMode(bool enabled, bool frozen);
455 virtual void setInputFilterEnabled(bool enabled);
456@@ -922,7 +941,7 @@
457 bool mDispatchFrozen;
458 bool mInputFilterEnabled;
459
460- Vector<sp<InputWindowHandle> > mWindowHandles;
461+ sp<InputEnumerator> mEnumerator;
462
463 sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
464 bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
465@@ -1096,6 +1115,8 @@
466 // Statistics gathering.
467 void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
468 int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
469+
470+ void setKeyboardFocusLocked(const sp<InputWindowHandle>& windowHandle);
471 };
472
473 /* Enqueues and dispatches input events, endlessly. */
474
475=== added file '3rd_party/android-input/android/frameworks/base/services/input/InputEnumerator.h'
476--- 3rd_party/android-input/android/frameworks/base/services/input/InputEnumerator.h 1970-01-01 00:00:00 +0000
477+++ 3rd_party/android-input/android/frameworks/base/services/input/InputEnumerator.h 2013-05-30 19:33:26 +0000
478@@ -0,0 +1,43 @@
479+/*
480+ * Copyright (C) 2013 Canonical LTD
481+ *
482+ * Licensed under the Apache License, Version 2.0 (the "License");
483+ * you may not use this file except in compliance with the License.
484+ * You may obtain a copy of the License at
485+ *
486+ * http://www.apache.org/licenses/LICENSE-2.0
487+ *
488+ * Unless required by applicable law or agreed to in writing, software
489+ * distributed under the License is distributed on an "AS IS" BASIS,
490+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
491+ * See the License for the specific language governing permissions and
492+ * limitations under the License.
493+ *
494+ * Author: Robert Carr <robert.carr@canonical.com>
495+ */
496+
497+// TODO: ~racarr. What license should this file be under?
498+
499+#ifndef _UI_INPUT_ENUMERATOR_H
500+#define _UI_INPUT_ENUMERATOR_H
501+
502+#include <std/RefBase.h>
503+
504+#include <functional>
505+
506+namespace android
507+{
508+class InputWindowHandle;
509+
510+class InputEnumerator : public RefBase {
511+public:
512+ virtual void for_each(std::function<void(sp<InputWindowHandle> const&)> const& callback) = 0;
513+
514+protected:
515+ InputEnumerator() = default;
516+ virtual ~InputEnumerator() = default;
517+};
518+
519+} // namespace android
520+
521+#endif // _UI_INPUT_ENUMERATOR_H
522
523=== removed file '3rd_party/android-input/android/frameworks/base/services/input/InputManager.h'
524--- 3rd_party/android-input/android/frameworks/base/services/input/InputManager.h 2013-05-03 16:38:07 +0000
525+++ 3rd_party/android-input/android/frameworks/base/services/input/InputManager.h 1970-01-01 00:00:00 +0000
526@@ -1,109 +0,0 @@
527-/*
528- * Copyright (C) 2010 The Android Open Source Project
529- *
530- * Licensed under the Apache License, Version 2.0 (the "License");
531- * you may not use this file except in compliance with the License.
532- * You may obtain a copy of the License at
533- *
534- * http://www.apache.org/licenses/LICENSE-2.0
535- *
536- * Unless required by applicable law or agreed to in writing, software
537- * distributed under the License is distributed on an "AS IS" BASIS,
538- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
539- * See the License for the specific language governing permissions and
540- * limitations under the License.
541- */
542-
543-#ifndef _UI_INPUT_MANAGER_H
544-#define _UI_INPUT_MANAGER_H
545-
546-/**
547- * Native input manager.
548- */
549-
550-#include "EventHub.h"
551-#include "InputReader.h"
552-#include "InputDispatcher.h"
553-
554-#include <androidfw/Input.h>
555-#include <androidfw/InputTransport.h>
556-#include <std/Errors.h>
557-#include <std/Vector.h>
558-#include <std/Timers.h>
559-#include <std/RefBase.h>
560-#include <std/String8.h>
561-
562-namespace android {
563-
564-/*
565- * The input manager is the core of the system event processing.
566- *
567- * The input manager uses two threads.
568- *
569- * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
570- * applies policy, and posts messages to a queue managed by the DispatcherThread.
571- * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
572- * queue and asynchronously dispatches them to applications.
573- *
574- * By design, the InputReaderThread class and InputDispatcherThread class do not share any
575- * internal state. Moreover, all communication is done one way from the InputReaderThread
576- * into the InputDispatcherThread and never the reverse. Both classes may interact with the
577- * InputDispatchPolicy, however.
578- *
579- * The InputManager class never makes any calls into Java itself. Instead, the
580- * InputDispatchPolicy is responsible for performing all external interactions with the
581- * system, including calling DVM services.
582- */
583-class InputManagerInterface : public virtual RefBase {
584-protected:
585- InputManagerInterface() { }
586- virtual ~InputManagerInterface() { }
587-
588-public:
589- /* Starts the input manager threads. */
590- virtual status_t start() = 0;
591-
592- /* Stops the input manager threads and waits for them to exit. */
593- virtual status_t stop() = 0;
594-
595- /* Gets the input reader. */
596- virtual sp<InputReaderInterface> getReader() = 0;
597-
598- /* Gets the input dispatcher. */
599- virtual sp<InputDispatcherInterface> getDispatcher() = 0;
600-};
601-
602-class InputManager : public InputManagerInterface {
603-protected:
604- virtual ~InputManager();
605-
606-public:
607- InputManager(
608- const sp<EventHubInterface>& eventHub,
609- const sp<InputReaderPolicyInterface>& readerPolicy,
610- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
611-
612- // (used for testing purposes)
613- InputManager(
614- const sp<InputReaderInterface>& reader,
615- const sp<InputDispatcherInterface>& dispatcher);
616-
617- virtual status_t start();
618- virtual status_t stop();
619-
620- virtual sp<InputReaderInterface> getReader();
621- virtual sp<InputDispatcherInterface> getDispatcher();
622-
623-private:
624- sp<InputReaderInterface> mReader;
625- sp<InputReaderThread> mReaderThread;
626-
627- sp<InputDispatcherInterface> mDispatcher;
628- sp<InputDispatcherThread> mDispatcherThread;
629-
630- void initialize();
631-};
632-
633-} // namespace android
634-
635-#endif // _UI_INPUT_MANAGER_H
636
637=== removed directory '3rd_party/android-input/tools'
638=== modified file 'examples/render_surfaces.cpp'
639--- examples/render_surfaces.cpp 2013-05-21 17:16:43 +0000
640+++ examples/render_surfaces.cpp 2013-05-30 19:33:26 +0000
641@@ -24,7 +24,6 @@
642 #include "mir/graphics/buffer_initializer.h"
643 #include "mir/graphics/cursor.h"
644 #include "mir/graphics/display.h"
645-#include "mir/input/null_input_manager.h"
646 #include "mir/shell/surface_builder.h"
647 #include "mir/surfaces/surface.h"
648 #include "mir/default_server_configuration.h"
649
650=== modified file 'include/server/mir/default_server_configuration.h'
651--- include/server/mir/default_server_configuration.h 2013-05-28 17:15:21 +0000
652+++ include/server/mir/default_server_configuration.h 2013-05-30 19:33:26 +0000
653@@ -51,7 +51,7 @@
654 {
655 class SurfaceFactory;
656 class SurfaceBuilder;
657-class InputTargetListener;
658+class InputTargeter;
659 class SessionContainer;
660 class FocusSetter;
661 class FocusSequence;
662@@ -70,6 +70,7 @@
663 class SurfaceStackModel;
664 class SurfaceStack;
665 class SurfaceController;
666+class InputRegistrar;
667 }
668 namespace graphics
669 {
670@@ -86,11 +87,8 @@
671 class InputManager;
672 class EventFilter;
673 class InputChannelFactory;
674-namespace android
675-{
676 class InputConfiguration;
677 }
678-}
679
680 namespace logging
681 {
682@@ -185,9 +183,10 @@
683 /** @name input configuration
684 * @{ */
685 virtual std::shared_ptr<input::InputReport> the_input_report();
686- virtual std::shared_ptr<input::android::InputConfiguration> the_input_configuration();
687+ virtual std::shared_ptr<input::InputConfiguration> the_input_configuration();
688 virtual std::initializer_list<std::shared_ptr<input::EventFilter> const> the_event_filters();
689- virtual std::shared_ptr<shell::InputTargetListener> the_input_target_listener();
690+ virtual std::shared_ptr<surfaces::InputRegistrar> the_input_registrar();
691+ virtual std::shared_ptr<shell::InputTargeter> the_input_targeter();
692 /** @} */
693
694 /** @name logging configuration - customization
695@@ -213,10 +212,13 @@
696 CachedPtr<frontend::Communicator> communicator;
697 CachedPtr<shell::SessionManager> session_manager;
698
699+
700+ std::shared_ptr<input::InputConfiguration> input_configuration;
701+
702 CachedPtr<input::InputReport> input_report;
703- std::shared_ptr<input::android::InputConfiguration> input_configuration;
704 CachedPtr<input::InputManager> input_manager;
705- CachedPtr<shell::InputTargetListener> input_target_listener;
706+ CachedPtr<surfaces::InputRegistrar> input_registrar;
707+ CachedPtr<shell::InputTargeter> input_targeter;
708 CachedPtr<graphics::Platform> graphics_platform;
709 CachedPtr<graphics::BufferInitializer> buffer_initializer;
710 CachedPtr<compositor::GraphicBufferAllocator> buffer_allocator;
711
712=== renamed file 'include/server/mir/input/android/android_input_configuration.h' => 'include/server/mir/input/input_configuration.h'
713--- include/server/mir/input/android/android_input_configuration.h 2013-04-24 05:22:20 +0000
714+++ include/server/mir/input/input_configuration.h 2013-05-30 19:33:26 +0000
715@@ -16,38 +16,36 @@
716 * Authored by: Robert Carr <robert.carr@canonical.com>
717 */
718
719-#ifndef MIR_INPUT_ANDROID_INPUT_CONFIGURATION_H_
720-#define MIR_INPUT_ANDROID_INPUT_CONFIGURATION_H_
721-
722-#include <utils/StrongPointer.h>
723+#ifndef MIR_INPUT_INPUT_CONFIGURATION_H_
724+#define MIR_INPUT_INPUT_CONFIGURATION_H_
725
726 #include <memory>
727
728-namespace droidinput = android;
729-
730-namespace android
731-{
732-class EventHubInterface;
733-class InputDispatcherInterface;
734-}
735-
736 namespace mir
737 {
738+namespace surfaces
739+{
740+class InputRegistrar;
741+}
742+namespace shell
743+{
744+class InputTargeter;
745+}
746 namespace input
747 {
748-namespace android
749-{
750-class InputThread;
751+class InputTargets;
752+class InputManager;
753
754 class InputConfiguration
755 {
756 public:
757 virtual ~InputConfiguration() {}
758
759- virtual droidinput::sp<droidinput::EventHubInterface> the_event_hub() = 0;
760- virtual droidinput::sp<droidinput::InputDispatcherInterface> the_dispatcher() = 0;
761- virtual std::shared_ptr<InputThread> the_dispatcher_thread() = 0;
762- virtual std::shared_ptr<InputThread> the_reader_thread() = 0;
763+ virtual std::shared_ptr<surfaces::InputRegistrar> the_input_registrar() = 0;
764+ virtual std::shared_ptr<shell::InputTargeter> the_input_targeter() = 0;
765+ virtual std::shared_ptr<input::InputManager> the_input_manager() = 0;
766+
767+ virtual void set_input_targets(std::shared_ptr<input::InputTargets> const& targets) = 0;
768
769 protected:
770 InputConfiguration() = default;
771@@ -55,7 +53,6 @@
772 InputConfiguration& operator=(InputConfiguration const&) = delete;
773 };
774 }
775-}
776 } // namespace mir
777
778-#endif // MIR_INPUT_ANDROID_INPUT_CONFIGURATION_H_
779+#endif // MIR_INPUT_INPUT_CONFIGURATION_H_
780
781=== added file 'include/server/mir/input/input_targets.h'
782--- include/server/mir/input/input_targets.h 1970-01-01 00:00:00 +0000
783+++ include/server/mir/input/input_targets.h 2013-05-30 19:33:26 +0000
784@@ -0,0 +1,49 @@
785+/*
786+ * Copyright © 2012 Canonical Ltd.
787+ *
788+ * This program is free software: you can redistribute it and/or modify it
789+ * under the terms of the GNU General Public License version 3,
790+ * as published by the Free Software Foundation.
791+ *
792+ * This program is distributed in the hope that it will be useful,
793+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
794+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
795+ * GNU General Public License for more details.
796+ *
797+ * You should have received a copy of the GNU General Public License
798+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
799+ *
800+ * Authored by: Robert Carr <robert.carr@canonical.com>
801+ * Daniel d'Andradra <daniel.dandrada@canonical.com>
802+ */
803+
804+#ifndef MIR_INPUT_INPUT_TARGETS_H_
805+#define MIR_INPUT_INPUT_TARGETS_H_
806+
807+#include "mir/input/input_channel_factory.h"
808+
809+#include <memory>
810+
811+namespace mir
812+{
813+namespace input
814+{
815+class SurfaceTarget;
816+
817+class InputTargets
818+{
819+public:
820+ virtual ~InputTargets() = default;
821+
822+ virtual void for_each(std::function<void(std::shared_ptr<input::SurfaceTarget> const&)> const& callback) = 0;
823+
824+protected:
825+ InputTargets() = default;
826+ InputTargets(InputTargets const&) = delete;
827+ InputTargets& operator=(InputTargets const&) = delete;
828+};
829+
830+}
831+}
832+
833+#endif // MIR_INPUT_INPUT_TARGETS
834
835=== added file 'include/server/mir/input/null_input_configuration.h'
836--- include/server/mir/input/null_input_configuration.h 1970-01-01 00:00:00 +0000
837+++ include/server/mir/input/null_input_configuration.h 2013-05-30 19:33:26 +0000
838@@ -0,0 +1,49 @@
839+/*
840+ * Copyright © 2013 Canonical Ltd.
841+ *
842+ * This program is free software: you can redistribute it and/or modify it
843+ * under the terms of the GNU General Public License version 3,
844+ * as published by the Free Software Foundation.
845+ *
846+ * This program is distributed in the hope that it will be useful,
847+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
848+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
849+ * GNU General Public License for more details.
850+ *
851+ * You should have received a copy of the GNU General Public License
852+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
853+ *
854+ * Authored by: Robert Carr <robert.carr@canonical.com>
855+ */
856+
857+#ifndef MIR_INPUT_NULL_INPUT_CONFIGURATION_H_
858+#define MIR_INPUT_NULL_INPUT_CONFIGURATION_H_
859+
860+#include "mir/input/input_configuration.h"
861+
862+namespace mir
863+{
864+namespace input
865+{
866+
867+class NullInputConfiguration : public InputConfiguration
868+{
869+public:
870+ NullInputConfiguration() = default;
871+ virtual ~NullInputConfiguration() = default;
872+
873+ std::shared_ptr<surfaces::InputRegistrar> the_input_registrar();
874+ std::shared_ptr<shell::InputTargeter> the_input_targeter();
875+ std::shared_ptr<InputManager> the_input_manager();
876+
877+ void set_input_targets(std::shared_ptr<InputTargets> const& /* targets */);
878+
879+protected:
880+ NullInputConfiguration(const NullInputConfiguration&) = delete;
881+ NullInputConfiguration& operator=(const NullInputConfiguration&) = delete;
882+};
883+
884+}
885+}
886+
887+#endif // MIR_INPUT_NULL_INPUT_CONFIGURATION
888
889=== removed file 'include/server/mir/input/null_input_manager.h'
890--- include/server/mir/input/null_input_manager.h 2013-05-02 00:11:18 +0000
891+++ include/server/mir/input/null_input_manager.h 1970-01-01 00:00:00 +0000
892@@ -1,51 +0,0 @@
893-/*
894- * Copyright © 2013 Canonical Ltd.
895- *
896- * This program is free software: you can redistribute it and/or modify it
897- * under the terms of the GNU General Public License version 3,
898- * as published by the Free Software Foundation.
899- *
900- * This program is distributed in the hope that it will be useful,
901- * but WITHOUT ANY WARRANTY; without even the implied warranty of
902- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
903- * GNU General Public License for more details.
904- *
905- * You should have received a copy of the GNU General Public License
906- * along with this program. If not, see <http://www.gnu.org/licenses/>.
907- *
908- * Authored by: Robert Carr <robert.carr@canonical.com>
909- */
910-
911-#ifndef MIR_INPUT_NULL_INPUT_MANAGER_H_
912-#define MIR_INPUT_NULL_INPUT_MANAGER_H_
913-
914-#include "mir/input/input_manager.h"
915-
916-namespace mir
917-{
918-namespace input
919-{
920-
921-class NullInputManager : public InputManager
922-{
923-public:
924- NullInputManager() {};
925- virtual ~NullInputManager() {}
926-
927- void start() {}
928- void stop() {}
929-
930- std::shared_ptr<InputChannel> make_input_channel()
931- {
932- return std::shared_ptr<InputChannel>();
933- }
934-
935-protected:
936- NullInputManager(const NullInputManager&) = delete;
937- NullInputManager& operator=(const NullInputManager&) = delete;
938-};
939-
940-}
941-}
942-
943-#endif // MIR_INPUT_NULL_INPUT_MANAGER
944
945=== removed file 'include/server/mir/input/null_input_target_listener.h'
946--- include/server/mir/input/null_input_target_listener.h 2013-05-02 00:11:18 +0000
947+++ include/server/mir/input/null_input_target_listener.h 1970-01-01 00:00:00 +0000
948@@ -1,63 +0,0 @@
949-/*
950- * Copyright © 2013 Canonical Ltd.
951- *
952- * This program is free software: you can redistribute it and/or modify it
953- * under the terms of the GNU General Public License version 3,
954- * as published by the Free Software Foundation.
955- *
956- * This program is distributed in the hope that it will be useful,
957- * but WITHOUT ANY WARRANTY; without even the implied warranty of
958- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
959- * GNU General Public License for more details.
960- *
961- * You should have received a copy of the GNU General Public License
962- * along with this program. If not, see <http://www.gnu.org/licenses/>.
963- *
964- * Authored by: Robert Carr <robert.carr@canonical.com>
965- */
966-
967-#ifndef MIR_INPUT_NULL_INPUT_TARGET_LISTENER_H_
968-#define MIR_INPUT_NULL_INPUT_TARGET_LISTENER_H_
969-
970-#include "mir/shell/input_target_listener.h"
971-
972-namespace mir
973-{
974-namespace input
975-{
976-
977-class NullInputTargetListener : public shell::InputTargetListener
978-{
979-public:
980- NullInputTargetListener() {};
981- virtual ~NullInputTargetListener() noexcept(true) {}
982-
983- virtual void input_application_opened(std::shared_ptr<input::SessionTarget> const&)
984- {
985- }
986- virtual void input_application_closed(std::shared_ptr<input::SessionTarget> const&)
987- {
988- }
989- virtual void input_surface_opened(std::shared_ptr<input::SessionTarget> const&,
990- std::shared_ptr<input::SurfaceTarget> const&)
991- {
992- }
993- virtual void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const&)
994- {
995- }
996- virtual void focus_changed(std::shared_ptr<input::SurfaceTarget> const&)
997- {
998- }
999- virtual void focus_cleared()
1000- {
1001- }
1002-
1003-protected:
1004- NullInputTargetListener(const NullInputTargetListener&) = delete;
1005- NullInputTargetListener& operator=(const NullInputTargetListener&) = delete;
1006-};
1007-
1008-}
1009-}
1010-
1011-#endif // MIR_INPUT_NULL_INPUT_TARGET_LISTENER_H_
1012
1013=== removed file 'include/server/mir/input/session_target.h'
1014--- include/server/mir/input/session_target.h 2013-04-24 05:22:20 +0000
1015+++ include/server/mir/input/session_target.h 1970-01-01 00:00:00 +0000
1016@@ -1,45 +0,0 @@
1017-/*
1018- * Copyright © 2013 Canonical Ltd.
1019- *
1020- * This program is free software: you can redistribute it and/or modify it
1021- * under the terms of the GNU General Public License version 3,
1022- * as published by the Free Software Foundation.
1023- *
1024- * This program is distributed in the hope that it will be useful,
1025- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1026- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1027- * GNU General Public License for more details.
1028- *
1029- * You should have received a copy of the GNU General Public License
1030- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1031- *
1032- * Authored by: Robert Carr <robert.carr@canonical.com>
1033- */
1034-
1035-#ifndef MIR_INPUT_SESSION_TARGET_H_
1036-#define MIR_INPUT_SESSION_TARGET_H_
1037-
1038-#include <string>
1039-
1040-namespace mir
1041-{
1042-namespace input
1043-{
1044-
1045-class SessionTarget
1046-{
1047-public:
1048- virtual ~SessionTarget() {}
1049-
1050- virtual std::string name() const = 0;
1051-
1052-protected:
1053- SessionTarget() = default;
1054- SessionTarget(SessionTarget const&) = delete;
1055- SessionTarget& operator=(SessionTarget const&) = delete;
1056-};
1057-
1058-}
1059-} // namespace mir
1060-
1061-#endif // MIR_INPUT_SESSION_TARGET_H_
1062
1063=== modified file 'include/server/mir/input/surface_target.h'
1064--- include/server/mir/input/surface_target.h 2013-04-26 16:12:22 +0000
1065+++ include/server/mir/input/surface_target.h 2013-05-30 19:33:26 +0000
1066@@ -36,7 +36,7 @@
1067
1068 virtual geometry::Point top_left() const = 0;
1069 virtual geometry::Size size() const = 0;
1070- virtual std::string name() const = 0;
1071+ virtual std::string const& name() const = 0;
1072
1073 virtual int server_input_fd() const = 0;
1074
1075
1076=== modified file 'include/server/mir/shell/application_session.h'
1077--- include/server/mir/shell/application_session.h 2013-05-21 17:16:43 +0000
1078+++ include/server/mir/shell/application_session.h 2013-05-30 19:33:26 +0000
1079@@ -33,17 +33,14 @@
1080 {
1081 class SurfaceFactory;
1082 class Surface;
1083-class InputTargetListener;
1084
1085 class ApplicationSession : public Session
1086 {
1087 public:
1088- explicit ApplicationSession(std::shared_ptr<SurfaceFactory> const& surface_factory,
1089- std::shared_ptr<InputTargetListener> const& input_target_listener, std::string const& session_name);
1090+ explicit ApplicationSession(std::shared_ptr<SurfaceFactory> const& surface_factory, std::string const& session_name);
1091
1092 ApplicationSession(
1093 std::shared_ptr<SurfaceFactory> const& surface_factory,
1094- std::shared_ptr<InputTargetListener> const& input_target_listener,
1095 std::string const& session_name,
1096 std::shared_ptr<events::EventSink> const& sink);
1097
1098@@ -70,7 +67,6 @@
1099
1100 private:
1101 std::shared_ptr<SurfaceFactory> const surface_factory;
1102- std::shared_ptr<InputTargetListener> const input_target_listener;
1103 std::string const session_name;
1104 std::shared_ptr<events::EventSink> const event_sink;
1105
1106
1107=== removed file 'include/server/mir/shell/input_target_listener.h'
1108--- include/server/mir/shell/input_target_listener.h 2013-04-19 17:44:48 +0000
1109+++ include/server/mir/shell/input_target_listener.h 1970-01-01 00:00:00 +0000
1110@@ -1,59 +0,0 @@
1111-/*
1112- * Copyright © 2013 Canonical Ltd.
1113- *
1114- * This program is free software: you can redistribute it and/or modify it
1115- * under the terms of the GNU General Public License version 3,
1116- * as published by the Free Software Foundation.
1117- *
1118- * This program is distributed in the hope that it will be useful,
1119- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1120- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1121- * GNU General Public License for more details.
1122- *
1123- * You should have received a copy of the GNU General Public License
1124- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1125- *
1126- * Authored by: Robert Carr <robert.carr@canonical.com>
1127- */
1128-
1129-#ifndef MIR_SHELL_INPUT_TARGET_LISTENER_H_
1130-#define MIR_SHELL_INPUT_TARGET_LISTENER_H_
1131-
1132-#include <memory>
1133-
1134-namespace mir
1135-{
1136-namespace input
1137-{
1138-class SessionTarget;
1139-class SurfaceTarget;
1140-}
1141-
1142-namespace shell
1143-{
1144-
1145-class InputTargetListener
1146-{
1147-public:
1148- virtual ~InputTargetListener() = default;
1149-
1150- virtual void input_application_opened(std::shared_ptr<input::SessionTarget> const& application) = 0;
1151- virtual void input_application_closed(std::shared_ptr<input::SessionTarget> const& application) = 0;
1152-
1153- virtual void input_surface_opened(std::shared_ptr<input::SessionTarget> const& application,
1154- std::shared_ptr<input::SurfaceTarget> const& opened_surface) = 0;
1155- virtual void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface) = 0;
1156-
1157- virtual void focus_changed(std::shared_ptr<input::SurfaceTarget> const& focus_surface) = 0;
1158- virtual void focus_cleared() = 0;
1159-
1160-protected:
1161- InputTargetListener() = default;
1162- InputTargetListener(InputTargetListener const&) = delete;
1163- InputTargetListener& operator=(InputTargetListener const&) = delete;
1164-};
1165-
1166-}
1167-} // namespace mir
1168-
1169-#endif // MIR_SHELL_INPUT_TARGET_LISTENER_H_
1170
1171=== added file 'include/server/mir/shell/input_targeter.h'
1172--- include/server/mir/shell/input_targeter.h 1970-01-01 00:00:00 +0000
1173+++ include/server/mir/shell/input_targeter.h 2013-05-30 19:33:26 +0000
1174@@ -0,0 +1,52 @@
1175+/*
1176+ * Copyright © 2013 Canonical Ltd.
1177+ *
1178+ * This program is free software: you can redistribute it and/or modify it
1179+ * under the terms of the GNU General Public License version 3,
1180+ * as published by the Free Software Foundation.
1181+ *
1182+ * This program is distributed in the hope that it will be useful,
1183+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1184+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1185+ * GNU General Public License for more details.
1186+ *
1187+ * You should have received a copy of the GNU General Public License
1188+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1189+ *
1190+ * Authored by: Robert Carr <robert.carr@canonical.com>
1191+ */
1192+
1193+#ifndef MIR_SHELL_INPUT_TARGETER_H_
1194+#define MIR_SHELL_INPUT_TARGETER_H_
1195+
1196+#include <memory>
1197+
1198+namespace mir
1199+{
1200+namespace input
1201+{
1202+class SurfaceTarget;
1203+}
1204+
1205+namespace shell
1206+{
1207+
1208+/// An interface used to control the selection of keyboard input focus.
1209+class InputTargeter
1210+{
1211+public:
1212+ virtual ~InputTargeter() = default;
1213+
1214+ virtual void focus_changed(std::shared_ptr<input::SurfaceTarget const> const& focus_surface) = 0;
1215+ virtual void focus_cleared() = 0;
1216+
1217+protected:
1218+ InputTargeter() = default;
1219+ InputTargeter(InputTargeter const&) = delete;
1220+ InputTargeter& operator=(InputTargeter const&) = delete;
1221+};
1222+
1223+}
1224+} // namespace mir
1225+
1226+#endif // MIR_SHELL_INPUT_TARGETER_H_
1227
1228=== modified file 'include/server/mir/shell/session.h'
1229--- include/server/mir/shell/session.h 2013-04-25 09:48:54 +0000
1230+++ include/server/mir/shell/session.h 2013-05-30 19:33:26 +0000
1231@@ -20,7 +20,6 @@
1232 #define MIR_SHELL_SESSION_H_
1233
1234 #include "mir/frontend/session.h"
1235-#include "mir/input/session_target.h"
1236
1237 namespace mir
1238 {
1239@@ -29,7 +28,7 @@
1240 {
1241 class Surface;
1242
1243-class Session : public frontend::Session, public input::SessionTarget
1244+class Session : public frontend::Session
1245 {
1246 public:
1247 virtual std::string name() const = 0;
1248
1249=== modified file 'include/server/mir/shell/session_manager.h'
1250--- include/server/mir/shell/session_manager.h 2013-05-21 17:16:43 +0000
1251+++ include/server/mir/shell/session_manager.h 2013-05-30 19:33:26 +0000
1252@@ -38,7 +38,7 @@
1253 class FocusSequence;
1254 class FocusSetter;
1255 class Session;
1256-class InputTargetListener;
1257+class InputRegistrar;
1258 class SessionListener;
1259 struct SurfaceCreationParameters;
1260
1261@@ -49,7 +49,6 @@
1262 std::shared_ptr<SessionContainer> const& app_container,
1263 std::shared_ptr<FocusSequence> const& focus_sequence,
1264 std::shared_ptr<FocusSetter> const& focus_setter,
1265- std::shared_ptr<InputTargetListener> const& input_target_listener,
1266 std::shared_ptr<SessionListener> const& session_listener);
1267 virtual ~SessionManager();
1268
1269@@ -70,7 +69,6 @@
1270 std::shared_ptr<SessionContainer> const app_container;
1271 std::shared_ptr<FocusSequence> const focus_sequence;
1272 std::shared_ptr<FocusSetter> const focus_setter;
1273- std::shared_ptr<InputTargetListener> const input_target_listener;
1274 std::shared_ptr<SessionListener> const session_listener;
1275
1276 std::mutex mutex;
1277
1278=== modified file 'include/server/mir/shell/single_visibility_focus_mechanism.h'
1279--- include/server/mir/shell/single_visibility_focus_mechanism.h 2013-05-02 00:11:18 +0000
1280+++ include/server/mir/shell/single_visibility_focus_mechanism.h 2013-05-30 19:33:26 +0000
1281@@ -28,11 +28,13 @@
1282 namespace shell
1283 {
1284 class SessionContainer;
1285+class InputTargeter;
1286
1287 class SingleVisibilityFocusMechanism : public FocusSetter
1288 {
1289 public:
1290- explicit SingleVisibilityFocusMechanism(std::shared_ptr<SessionContainer> const& app_container);
1291+ explicit SingleVisibilityFocusMechanism(std::shared_ptr<SessionContainer> const& app_container,
1292+ std::shared_ptr<InputTargeter> const& input_targeter);
1293 virtual ~SingleVisibilityFocusMechanism() {}
1294
1295 void set_focus_to(std::shared_ptr<shell::Session> const& new_focus);
1296@@ -40,8 +42,10 @@
1297 protected:
1298 SingleVisibilityFocusMechanism(const SingleVisibilityFocusMechanism&) = delete;
1299 SingleVisibilityFocusMechanism& operator=(const SingleVisibilityFocusMechanism&) = delete;
1300+
1301 private:
1302 std::shared_ptr<SessionContainer> const app_container;
1303+ std::shared_ptr<InputTargeter> const input_targeter;
1304 };
1305
1306 }
1307
1308=== modified file 'include/server/mir/shell/surface.h'
1309--- include/server/mir/shell/surface.h 2013-05-22 17:11:51 +0000
1310+++ include/server/mir/shell/surface.h 2013-05-30 19:33:26 +0000
1311@@ -23,7 +23,6 @@
1312 #include "mir/frontend/surface.h"
1313 #include "mir/frontend/surface_id.h"
1314 #include "mir/surfaces/surface.h"
1315-#include "mir/input/surface_target.h"
1316
1317 #include "mir_toolkit/common.h"
1318
1319@@ -35,28 +34,23 @@
1320 {
1321 class EventSink;
1322 }
1323-namespace input
1324-{
1325-class InputChannel;
1326-}
1327
1328 namespace shell
1329 {
1330+class InputTargeter;
1331 class SurfaceBuilder;
1332 struct SurfaceCreationParameters;
1333
1334-class Surface : public frontend::Surface, public input::SurfaceTarget
1335+class Surface : public frontend::Surface
1336 {
1337 public:
1338 Surface(
1339 std::shared_ptr<SurfaceBuilder> const& builder,
1340- SurfaceCreationParameters const& params,
1341- std::shared_ptr<input::InputChannel> const& input_channel);
1342+ SurfaceCreationParameters const& params);
1343
1344 Surface(
1345 std::shared_ptr<SurfaceBuilder> const& builder,
1346 SurfaceCreationParameters const& params,
1347- std::shared_ptr<input::InputChannel> const& input_channel,
1348 frontend::SurfaceId id,
1349 std::shared_ptr<events::EventSink> const& sink);
1350
1351@@ -89,13 +83,14 @@
1352 virtual MirSurfaceType type() const;
1353 virtual MirSurfaceState state() const;
1354
1355+ virtual void take_input_focus(std::shared_ptr<InputTargeter> const& targeter);
1356+
1357 private:
1358 bool set_type(MirSurfaceType t); // Use configure() to make public changes
1359 bool set_state(MirSurfaceState s);
1360 void notify_change(MirSurfaceAttrib attrib, int value);
1361
1362 std::shared_ptr<SurfaceBuilder> const builder;
1363- std::shared_ptr<mir::input::InputChannel> const input_channel;
1364 std::weak_ptr<mir::surfaces::Surface> const surface;
1365
1366 frontend::SurfaceId const id;
1367
1368=== modified file 'include/server/mir/shell/surface_source.h'
1369--- include/server/mir/shell/surface_source.h 2013-05-21 17:16:43 +0000
1370+++ include/server/mir/shell/surface_source.h 2013-05-30 19:33:26 +0000
1371@@ -25,10 +25,6 @@
1372
1373 namespace mir
1374 {
1375-namespace input
1376-{
1377-class InputChannelFactory;
1378-}
1379
1380 namespace shell
1381 {
1382@@ -37,7 +33,7 @@
1383 class SurfaceSource : public SurfaceFactory
1384 {
1385 public:
1386- explicit SurfaceSource(std::shared_ptr<SurfaceBuilder> const& surface_builder, std::shared_ptr<input::InputChannelFactory> const& input_factory);
1387+ explicit SurfaceSource(std::shared_ptr<SurfaceBuilder> const& surface_builder);
1388 virtual ~SurfaceSource() {}
1389
1390 std::shared_ptr<Surface> create_surface(
1391@@ -51,7 +47,6 @@
1392
1393 private:
1394 std::shared_ptr<SurfaceBuilder> const surface_builder;
1395- std::shared_ptr<input::InputChannelFactory> const input_factory;
1396 };
1397
1398 }
1399
1400=== added file 'include/server/mir/surfaces/input_registrar.h'
1401--- include/server/mir/surfaces/input_registrar.h 1970-01-01 00:00:00 +0000
1402+++ include/server/mir/surfaces/input_registrar.h 2013-05-30 19:33:26 +0000
1403@@ -0,0 +1,54 @@
1404+/*
1405+ * Copyright © 2013 Canonical Ltd.
1406+ *
1407+ * This program is free software: you can redistribute it and/or modify it
1408+ * under the terms of the GNU General Public License version 3,
1409+ * as published by the Free Software Foundation.
1410+ *
1411+ * This program is distributed in the hope that it will be useful,
1412+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1413+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+ * GNU General Public License for more details.
1415+ *
1416+ * You should have received a copy of the GNU General Public License
1417+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1418+ *
1419+ * Authored by: Robert Carr <robert.carr@canonical.com>
1420+ */
1421+
1422+#ifndef MIR_SURFACES_INPUT_REGISTRAR_H_
1423+#define MIR_SURFACES_INPUT_REGISTRAR_H_
1424+
1425+#include <memory>
1426+
1427+namespace mir
1428+{
1429+namespace input
1430+{
1431+class SessionTarget;
1432+class SurfaceTarget;
1433+}
1434+
1435+namespace surfaces
1436+{
1437+
1438+/// An interface used to register input targets and take care of input assosciation (i.e.
1439+/// create input channels).
1440+class InputRegistrar
1441+{
1442+public:
1443+ virtual ~InputRegistrar() = default;
1444+
1445+ virtual void input_surface_opened(std::shared_ptr<input::SurfaceTarget> const& opened_surface) = 0;
1446+ virtual void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface) = 0;
1447+
1448+protected:
1449+ InputRegistrar() = default;
1450+ InputRegistrar(InputRegistrar const&) = delete;
1451+ InputRegistrar& operator=(InputRegistrar const&) = delete;
1452+};
1453+
1454+}
1455+} // namespace mir
1456+
1457+#endif // MIR_SURFACES_INPUT_REGISTRAR_H_
1458
1459=== modified file 'include/server/mir/surfaces/surface.h'
1460--- include/server/mir/surfaces/surface.h 2013-05-20 22:55:43 +0000
1461+++ include/server/mir/surfaces/surface.h 2013-05-30 19:33:26 +0000
1462@@ -22,6 +22,7 @@
1463 #include "mir/geometry/pixel_format.h"
1464 #include "mir/graphics/renderable.h"
1465 #include "mir/compositor/buffer_properties.h"
1466+#include "mir/input/surface_target.h"
1467
1468 #include <memory>
1469 #include <string>
1470@@ -35,6 +36,10 @@
1471 struct BufferIPCPackage;
1472 class BufferID;
1473 }
1474+namespace input
1475+{
1476+class InputChannel;
1477+}
1478
1479 namespace surfaces
1480 {
1481@@ -42,11 +47,12 @@
1482
1483 // TODO this is ideally an implementation class. It is only in a public header
1484 // TODO because it is used in some example code (which probably needs rethinking).
1485-class Surface : public graphics::Renderable
1486+class Surface : public graphics::Renderable, public input::SurfaceTarget
1487 {
1488 public:
1489 Surface(const std::string& name, geometry::Point const& top_left,
1490 std::shared_ptr<BufferBundle> buffer_bundle,
1491+ std::shared_ptr<input::InputChannel> const& input_channel,
1492 std::function<void()> const& change_callback);
1493
1494 ~Surface();
1495@@ -74,12 +80,17 @@
1496 void force_requests_to_complete();
1497 void flag_for_render();
1498
1499+ bool supports_input() const;
1500+ int client_input_fd() const;
1501+ int server_input_fd() const;
1502 private:
1503 std::string surface_name;
1504 geometry::Point top_left_point;
1505
1506 std::shared_ptr<BufferBundle> buffer_bundle;
1507
1508+ std::shared_ptr<input::InputChannel> const input_channel;
1509+
1510 std::shared_ptr<compositor::Buffer> client_buffer_resource;
1511 glm::mat4 rotation_matrix;
1512 float alpha_value;
1513
1514=== modified file 'include/server/mir/surfaces/surface_stack.h'
1515--- include/server/mir/surfaces/surface_stack.h 2013-05-21 17:16:43 +0000
1516+++ include/server/mir/surfaces/surface_stack.h 2013-05-30 19:33:26 +0000
1517@@ -21,6 +21,7 @@
1518
1519 #include "surface_stack_model.h"
1520 #include "mir/compositor/renderables.h"
1521+#include "mir/input/input_targets.h"
1522
1523 #include <memory>
1524 #include <vector>
1525@@ -40,22 +41,34 @@
1526 struct SurfaceCreationParameters;
1527 }
1528
1529+namespace input
1530+{
1531+class InputChannelFactory;
1532+class SurfaceTarget;
1533+}
1534+
1535 /// Management of Surface objects. Includes the model (SurfaceStack and Surface
1536 /// classes) and controller (SurfaceController) elements of an MVC design.
1537 namespace surfaces
1538 {
1539 class BufferBundleFactory;
1540+class InputRegistrar;
1541 class Surface;
1542
1543-class SurfaceStack : public compositor::Renderables, public SurfaceStackModel
1544+class SurfaceStack : public compositor::Renderables, public input::InputTargets, public SurfaceStackModel
1545 {
1546 public:
1547- explicit SurfaceStack(std::shared_ptr<BufferBundleFactory> const& bb_factory);
1548- virtual ~SurfaceStack() = default;
1549+ explicit SurfaceStack(std::shared_ptr<BufferBundleFactory> const& bb_factory,
1550+ std::shared_ptr<input::InputChannelFactory> const& input_factory,
1551+ std::shared_ptr<InputRegistrar> const& input_registrar);
1552+ virtual ~SurfaceStack() noexcept(true) {}
1553
1554 // From Renderables
1555 virtual void for_each_if(compositor::FilterForRenderables &filter, compositor::OperatorForRenderables &renderable_operator);
1556 virtual void set_change_callback(std::function<void()> const& f);
1557+
1558+ // From InputTargets
1559+ void for_each(std::function<void(std::shared_ptr<input::SurfaceTarget> const&)> const& callback);
1560
1561 // From SurfaceStackModel
1562 virtual std::weak_ptr<Surface> create_surface(const shell::SurfaceCreationParameters& params);
1563@@ -70,6 +83,8 @@
1564
1565 std::mutex guard;
1566 std::shared_ptr<BufferBundleFactory> const buffer_bundle_factory;
1567+ std::shared_ptr<input::InputChannelFactory> const input_factory;
1568+ std::shared_ptr<InputRegistrar> const input_registrar;
1569 std::vector<std::shared_ptr<Surface>> surfaces;
1570 std::mutex notify_change_mutex;
1571 std::function<void()> notify_change;
1572
1573=== modified file 'include/test/mir_test_doubles/mock_input_configuration.h'
1574--- include/test/mir_test_doubles/mock_input_configuration.h 2013-04-24 05:22:20 +0000
1575+++ include/test/mir_test_doubles/mock_input_configuration.h 2013-05-30 19:33:26 +0000
1576@@ -40,6 +40,11 @@
1577 MOCK_METHOD0(the_dispatcher, droidinput::sp<droidinput::InputDispatcherInterface>());
1578 MOCK_METHOD0(the_dispatcher_thread, std::shared_ptr<input::android::InputThread>());
1579 MOCK_METHOD0(the_reader_thread, std::shared_ptr<input::android::InputThread>());
1580+
1581+ MOCK_METHOD0(the_input_registrar, std::shared_ptr<surfaces::InputRegistrar>());
1582+ MOCK_METHOD0(the_input_targeter, std::shared_ptr<shell::InputTargeter>());
1583+
1584+ MOCK_METHOD1(set_input_targets, void(std::shared_ptr<input::InputTargets> const&));
1585 };
1586
1587 }
1588
1589=== modified file 'include/test/mir_test_doubles/mock_input_dispatcher.h'
1590--- include/test/mir_test_doubles/mock_input_dispatcher.h 2013-04-24 05:22:20 +0000
1591+++ include/test/mir_test_doubles/mock_input_dispatcher.h 2013-05-30 19:33:26 +0000
1592@@ -34,17 +34,20 @@
1593 struct MockInputDispatcher : public droidinput::InputDispatcherInterface
1594 {
1595 // droidinput::InputDispatcher interface
1596+ MOCK_METHOD1(setInputEnumerator, void(droidinput::sp<droidinput::InputEnumerator> const&));
1597 MOCK_METHOD1(dump, void(droidinput::String8&));
1598 MOCK_METHOD0(monitor, void());
1599 MOCK_METHOD0(dispatchOnce, void());
1600 MOCK_METHOD6(injectInputEvent, int32_t(droidinput::InputEvent const*, int32_t, int32_t, int32_t, int32_t, uint32_t));
1601- MOCK_METHOD1(setInputWindows, void(droidinput::Vector<droidinput::sp<droidinput::InputWindowHandle>> const&));
1602 MOCK_METHOD1(setFocusedApplication, void(droidinput::sp<droidinput::InputApplicationHandle> const&));
1603 MOCK_METHOD2(setInputDispatchMode, void(bool, bool));
1604 MOCK_METHOD1(setInputFilterEnabled, void(bool));
1605 MOCK_METHOD2(transferTouchFocus, bool(droidinput::sp<droidinput::InputChannel> const&, droidinput::sp<droidinput::InputChannel> const&));
1606 MOCK_METHOD3(registerInputChannel, droidinput::status_t(droidinput::sp<droidinput::InputChannel> const&, droidinput::sp<droidinput::InputWindowHandle> const&, bool));
1607 MOCK_METHOD1(unregisterInputChannel, droidinput::status_t(droidinput::sp<droidinput::InputChannel> const&));
1608+
1609+ MOCK_METHOD1(setKeyboardFocus, void(droidinput::sp<droidinput::InputWindowHandle> const&));
1610+ MOCK_METHOD1(notifyWindowRemoved, void(droidinput::sp<droidinput::InputWindowHandle> const&));
1611
1612 // droidinput::InputListener interface
1613 MOCK_METHOD1(notifyConfigurationChanged, void(droidinput::NotifyConfigurationChangedArgs const*));
1614
1615=== renamed file 'include/test/mir_test_doubles/mock_input_target_listener.h' => 'include/test/mir_test_doubles/mock_input_registrar.h'
1616--- include/test/mir_test_doubles/mock_input_target_listener.h 2013-04-16 20:08:57 +0000
1617+++ include/test/mir_test_doubles/mock_input_registrar.h 2013-05-30 19:33:26 +0000
1618@@ -16,10 +16,10 @@
1619 * Authored by: Robert Carr <robert.carr@canonical.com>
1620 */
1621
1622-#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
1623-#define MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
1624+#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_REGISTRAR_H_
1625+#define MIR_TEST_DOUBLES_MOCK_INPUT_REGISTRAR_H_
1626
1627-#include "mir/shell/input_target_listener.h"
1628+#include "mir/surfaces/input_registrar.h"
1629
1630 #include <gmock/gmock.h>
1631
1632@@ -30,20 +30,15 @@
1633 namespace doubles
1634 {
1635
1636-struct MockInputTargetListener : public shell::InputTargetListener
1637+struct MockInputRegistrar : public surfaces::InputRegistrar
1638 {
1639- virtual ~MockInputTargetListener() noexcept(true) {}
1640- MOCK_METHOD1(input_application_opened, void(std::shared_ptr<input::SessionTarget> const& application));
1641- MOCK_METHOD1(input_application_closed, void(std::shared_ptr<input::SessionTarget> const& application));
1642- MOCK_METHOD2(input_surface_opened, void(std::shared_ptr<input::SessionTarget> const& application,
1643- std::shared_ptr<input::SurfaceTarget> const& opened_surface));
1644+ virtual ~MockInputRegistrar() noexcept(true) {}
1645+ MOCK_METHOD1(input_surface_opened, void(std::shared_ptr<input::SurfaceTarget> const& opened_surface));
1646 MOCK_METHOD1(input_surface_closed, void(std::shared_ptr<input::SurfaceTarget> const& closed_surface));
1647- MOCK_METHOD1(focus_changed, void(std::shared_ptr<input::SurfaceTarget> const& focus_surface));
1648- MOCK_METHOD0(focus_cleared, void());
1649 };
1650
1651 }
1652 }
1653 } // namespace mir
1654
1655-#endif // MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
1656+#endif // MIR_TEST_DOUBLES_MOCK_INPUT_REGISTRAR_H_
1657
1658=== added file 'include/test/mir_test_doubles/mock_input_targeter.h'
1659--- include/test/mir_test_doubles/mock_input_targeter.h 1970-01-01 00:00:00 +0000
1660+++ include/test/mir_test_doubles/mock_input_targeter.h 2013-05-30 19:33:26 +0000
1661@@ -0,0 +1,44 @@
1662+/*
1663+ * Copyright © 2013 Canonical Ltd.
1664+ *
1665+ * This program is free software: you can redistribute it and/or modify it
1666+ * under the terms of the GNU General Public License version 3,
1667+ * as published by the Free Software Foundation.
1668+ *
1669+ * This program is distributed in the hope that it will be useful,
1670+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1671+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1672+ * GNU General Public License for more details.
1673+ *
1674+ * You should have received a copy of the GNU General Public License
1675+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1676+ *
1677+ * Authored by: Robert Carr <robert.carr@canonical.com>
1678+ */
1679+
1680+#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_TARGETER_H_
1681+#define MIR_TEST_DOUBLES_MOCK_INPUT_TARGETER_H_
1682+
1683+#include "mir/shell/input_targeter.h"
1684+
1685+#include <gmock/gmock.h>
1686+
1687+namespace mir
1688+{
1689+namespace test
1690+{
1691+namespace doubles
1692+{
1693+
1694+struct MockInputTargeter : public shell::InputTargeter
1695+{
1696+ virtual ~MockInputTargeter() noexcept(true) {}
1697+ MOCK_METHOD1(focus_changed, void(std::shared_ptr<input::SurfaceTarget const> const& focus_surface));
1698+ MOCK_METHOD0(focus_cleared, void());
1699+};
1700+
1701+}
1702+}
1703+} // namespace mir
1704+
1705+#endif // MIR_TEST_DOUBLES_MOCK_INPUT_TARGETER_H_
1706
1707=== modified file 'include/test/mir_test_doubles/mock_surface.h'
1708--- include/test/mir_test_doubles/mock_surface.h 2013-05-21 17:16:43 +0000
1709+++ include/test/mir_test_doubles/mock_surface.h 2013-05-30 19:33:26 +0000
1710@@ -37,7 +37,7 @@
1711 struct MockSurface : public shell::Surface
1712 {
1713 MockSurface(std::shared_ptr<shell::SurfaceBuilder> const& builder) :
1714- shell::Surface(builder, shell::a_surface(), std::shared_ptr<input::InputChannel>())
1715+ shell::Surface(builder, shell::a_surface())
1716 {
1717 }
1718
1719@@ -57,6 +57,7 @@
1720 MOCK_CONST_METHOD0(server_input_fd, int());
1721
1722 MOCK_METHOD2(configure, int(MirSurfaceAttrib, int));
1723+ MOCK_METHOD1(take_input_focus, void(std::shared_ptr<shell::InputTargeter> const&));
1724 };
1725
1726 }
1727
1728=== renamed file 'include/test/mir_test_doubles/stub_input_target_listener.h' => 'include/test/mir_test_doubles/stub_input_registrar.h'
1729--- include/test/mir_test_doubles/stub_input_target_listener.h 2013-04-18 17:22:34 +0000
1730+++ include/test/mir_test_doubles/stub_input_registrar.h 2013-05-30 19:33:26 +0000
1731@@ -16,10 +16,10 @@
1732 * Authored by: Robert Carr <robert.carr@canonical.com>
1733 */
1734
1735-#ifndef MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
1736-#define MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
1737+#ifndef MIR_TEST_DOUBLES_STUB_INPUT_REGISTRAR_H_
1738+#define MIR_TEST_DOUBLES_STUB_INPUT_REGISTRAR_H_
1739
1740-#include "mir/shell/input_target_listener.h"
1741+#include "mir/surfaces/input_registrar.h"
1742
1743 namespace mir
1744 {
1745@@ -28,32 +28,18 @@
1746 namespace doubles
1747 {
1748
1749-struct StubInputTargetListener : public shell::InputTargetListener
1750+struct StubInputRegistrar : public surfaces::InputRegistrar
1751 {
1752- void input_application_opened(std::shared_ptr<input::SessionTarget> const&)
1753- {
1754- }
1755- void input_application_closed(std::shared_ptr<input::SessionTarget> const&)
1756- {
1757- }
1758- void input_surface_opened(std::shared_ptr<input::SessionTarget> const&,
1759- std::shared_ptr<input::SurfaceTarget> const&)
1760+ void input_surface_opened(std::shared_ptr<input::SurfaceTarget> const&)
1761 {
1762 }
1763 void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const&)
1764 {
1765 }
1766- void focus_changed(std::shared_ptr<input::SurfaceTarget> const&)
1767- {
1768- }
1769-
1770- void focus_cleared()
1771- {
1772- }
1773 };
1774
1775 }
1776 }
1777 } // namespace mir
1778
1779-#endif // MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
1780+#endif // MIR_TEST_DOUBLES_STUB_INPUT_REGISTRAR_H_
1781
1782=== added file 'include/test/mir_test_doubles/stub_input_targeter.h'
1783--- include/test/mir_test_doubles/stub_input_targeter.h 1970-01-01 00:00:00 +0000
1784+++ include/test/mir_test_doubles/stub_input_targeter.h 2013-05-30 19:33:26 +0000
1785@@ -0,0 +1,45 @@
1786+/*
1787+ * Copyright © 2013 Canonical Ltd.
1788+ *
1789+ * This program is free software: you can redistribute it and/or modify it
1790+ * under the terms of the GNU General Public License version 3,
1791+ * as published by the Free Software Foundation.
1792+ *
1793+ * This program is distributed in the hope that it will be useful,
1794+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1795+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1796+ * GNU General Public License for more details.
1797+ *
1798+ * You should have received a copy of the GNU General Public License
1799+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1800+ *
1801+ * Authored by: Robert Carr <robert.carr@canonical.com>
1802+ */
1803+
1804+#ifndef MIR_TEST_DOUBLES_STUB_INPUT_TARGETER_H_
1805+#define MIR_TEST_DOUBLES_STUB_INPUT_TARGETER_H_
1806+
1807+#include "mir/shell/input_targeter.h"
1808+
1809+namespace mir
1810+{
1811+namespace test
1812+{
1813+namespace doubles
1814+{
1815+
1816+struct StubInputTargeter : public shell::InputTargeter
1817+{
1818+ void focus_changed(std::shared_ptr<input::SurfaceTarget const> const&)
1819+ {
1820+ }
1821+ void focus_cleared()
1822+ {
1823+ }
1824+};
1825+
1826+}
1827+}
1828+} // namespace mir
1829+
1830+#endif // MIR_TEST_DOUBLES_STUB_INPUT_TARGETER_H_
1831
1832=== removed file 'include/test/mir_test_doubles/stub_session_target.h'
1833--- include/test/mir_test_doubles/stub_session_target.h 2013-04-24 05:22:20 +0000
1834+++ include/test/mir_test_doubles/stub_session_target.h 1970-01-01 00:00:00 +0000
1835@@ -1,44 +0,0 @@
1836-/*
1837- * Copyright © 2013 Canonical Ltd.
1838- *
1839- * This program is free software: you can redistribute it and/or modify it
1840- * under the terms of the GNU General Public License version 3,
1841- * as published by the Free Software Foundation.
1842- *
1843- * This program is distributed in the hope that it will be useful,
1844- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1845- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1846- * GNU General Public License for more details.
1847- *
1848- * You should have received a copy of the GNU General Public License
1849- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1850- *
1851- * Authored by: Robert Carr <robert.carr@canonical.com>
1852- */
1853-
1854-#ifndef MIR_TEST_DOUBLES_STUB_SESSION_TARGET_H_
1855-#define MIR_TEST_DOUBLES_STUB_SESSION_TARGET_H_
1856-
1857-#include "mir/input/session_target.h"
1858-
1859-namespace mir
1860-{
1861-namespace test
1862-{
1863-namespace doubles
1864-{
1865-
1866-struct StubSessionTarget : public input::SessionTarget
1867-{
1868- std::string name() const override
1869- {
1870- return std::string();
1871- }
1872-};
1873-
1874-}
1875-}
1876-} // namespace mir
1877-
1878-#endif // MIR_TEST_DOUBLES_STUB_SESSION_TARGET_H_
1879-
1880
1881=== modified file 'include/test/mir_test_doubles/stub_surface_builder.h'
1882--- include/test/mir_test_doubles/stub_surface_builder.h 2013-05-21 17:16:43 +0000
1883+++ include/test/mir_test_doubles/stub_surface_builder.h 2013-05-30 19:33:26 +0000
1884@@ -44,7 +44,8 @@
1885
1886 std::weak_ptr<surfaces::Surface> create_surface(shell::SurfaceCreationParameters const& param)
1887 {
1888- dummy_surface = std::make_shared<surfaces::Surface>(param.name, param.top_left, buffer_bundle, []{});
1889+ dummy_surface = std::make_shared<surfaces::Surface>(param.name, param.top_left, buffer_bundle,
1890+ std::shared_ptr<input::InputChannel>(), []{});
1891 return dummy_surface;
1892 }
1893
1894
1895=== modified file 'include/test/mir_test_doubles/stub_surface_target.h'
1896--- include/test/mir_test_doubles/stub_surface_target.h 2013-04-26 16:12:22 +0000
1897+++ include/test/mir_test_doubles/stub_surface_target.h 2013-05-30 19:33:26 +0000
1898@@ -47,9 +47,10 @@
1899 {
1900 return geometry::Point();
1901 }
1902- std::string name() const override
1903+ std::string const& name() const override
1904 {
1905- return std::string();
1906+ static std::string empty_name;
1907+ return empty_name;
1908 }
1909
1910 int input_fd;
1911
1912=== modified file 'include/test/mir_test_framework/testing_server_configuration.h'
1913--- include/test/mir_test_framework/testing_server_configuration.h 2013-05-02 00:11:18 +0000
1914+++ include/test/mir_test_framework/testing_server_configuration.h 2013-05-30 19:33:26 +0000
1915@@ -48,8 +48,7 @@
1916 // We override the_input_manager in the default server configuration
1917 // to avoid starting and stopping the full android input stack for tests
1918 // which do not leverage input.
1919- std::shared_ptr<input::InputManager> the_input_manager();
1920- std::shared_ptr<shell::InputTargetListener> the_input_target_listener();
1921+ std::shared_ptr<input::InputConfiguration> the_input_configuration();
1922
1923 virtual std::string the_socket_file() const;
1924 using DefaultServerConfiguration::the_options;
1925
1926=== modified file 'src/server/default_server_configuration.cpp'
1927--- src/server/default_server_configuration.cpp 2013-05-28 18:24:07 +0000
1928+++ src/server/default_server_configuration.cpp 2013-05-30 19:33:26 +0000
1929@@ -48,12 +48,11 @@
1930 #include "mir/graphics/buffer_initializer.h"
1931 #include "mir/graphics/null_display_report.h"
1932 #include "mir/input/cursor_listener.h"
1933-#include "mir/input/null_input_manager.h"
1934-#include "mir/input/null_input_target_listener.h"
1935+#include "mir/input/null_input_configuration.h"
1936 #include "mir/input/null_input_report.h"
1937 #include "input/android/default_android_input_configuration.h"
1938 #include "input/android/android_input_manager.h"
1939-#include "input/android/android_dispatcher_controller.h"
1940+#include "input/android/android_input_targeter.h"
1941 #include "mir/logging/logger.h"
1942 #include "mir/logging/input_report.h"
1943 #include "mir/logging/dumb_console_logger.h"
1944@@ -347,7 +346,7 @@
1945 [this]
1946 {
1947 return std::make_shared<msh::SingleVisibilityFocusMechanism>(
1948- the_shell_session_container());
1949+ the_shell_session_container(), the_input_targeter());
1950 });
1951 }
1952
1953@@ -393,7 +392,6 @@
1954 the_shell_session_container(),
1955 the_shell_focus_sequence(),
1956 the_shell_focus_setter(),
1957- the_input_target_listener(),
1958 the_shell_session_listener());
1959 });
1960 }
1961@@ -440,7 +438,7 @@
1962 });
1963 }
1964
1965-std::shared_ptr<mia::InputConfiguration>
1966+std::shared_ptr<mi::InputConfiguration>
1967 mir::DefaultServerConfiguration::the_input_configuration()
1968 {
1969 if (!input_configuration)
1970@@ -463,11 +461,18 @@
1971 std::weak_ptr<mg::Cursor> const cursor;
1972 };
1973
1974- input_configuration = std::make_shared<mia::DefaultInputConfiguration>(
1975- the_event_filters(),
1976- the_display(),
1977- std::make_shared<DefaultCursorListener>(the_display()->the_cursor()),
1978- the_input_report());
1979+ if (the_options()->get("enable-input", enable_input_default))
1980+ {
1981+ input_configuration = std::make_shared<mia::DefaultInputConfiguration>(
1982+ the_event_filters(),
1983+ the_display(),
1984+ std::make_shared<DefaultCursorListener>(the_display()->the_cursor()),
1985+ the_input_report());
1986+ }
1987+ else
1988+ {
1989+ input_configuration = std::make_shared<mi::NullInputConfiguration>();
1990+ }
1991 }
1992 return input_configuration;
1993 }
1994@@ -478,14 +483,9 @@
1995 return input_manager(
1996 [&, this]() -> std::shared_ptr<mi::InputManager>
1997 {
1998- if (the_options()->get("enable-input", enable_input_default))
1999- {
2000- if (the_options()->get(legacy_input_report_opt, off_opt_value) == log_opt_value)
2001+ if (the_options()->get(legacy_input_report_opt, off_opt_value) == log_opt_value)
2002 ml::legacy_input_report::initialize(the_logger());
2003- return std::make_shared<mia::InputManager>(the_input_configuration());
2004- }
2005- else
2006- return std::make_shared<mi::NullInputManager>();
2007+ return the_input_configuration()->the_input_manager();
2008 });
2009 }
2010
2011@@ -518,9 +518,11 @@
2012 mir::DefaultServerConfiguration::the_surface_stack_model()
2013 {
2014 return surface_stack(
2015- [this]()
2016+ [this]() -> std::shared_ptr<ms::SurfaceStack>
2017 {
2018- return std::make_shared<ms::SurfaceStack>(the_buffer_bundle_factory());
2019+ auto ss = std::make_shared<ms::SurfaceStack>(the_buffer_bundle_factory(), the_input_channel_factory(), the_input_registrar());
2020+ the_input_configuration()->set_input_targets(ss);
2021+ return ss;
2022 });
2023 }
2024
2025@@ -528,9 +530,11 @@
2026 mir::DefaultServerConfiguration::the_renderables()
2027 {
2028 return surface_stack(
2029- [this]()
2030+ [this]() -> std::shared_ptr<ms::SurfaceStack>
2031 {
2032- return std::make_shared<ms::SurfaceStack>(the_buffer_bundle_factory());
2033+ auto ss = std::make_shared<ms::SurfaceStack>(the_buffer_bundle_factory(), the_input_channel_factory(), the_input_registrar());
2034+ the_input_configuration()->set_input_targets(ss);
2035+ return ss;
2036 });
2037 }
2038
2039@@ -541,8 +545,7 @@
2040 [this]()
2041 {
2042 auto surface_source = std::make_shared<msh::SurfaceSource>(
2043- the_surface_builder(),
2044- the_input_channel_factory());
2045+ the_surface_builder());
2046
2047 return std::make_shared<msh::OrganisingSurfaceFactory>(
2048 surface_source,
2049@@ -691,15 +694,21 @@
2050 return the_input_manager();
2051 }
2052
2053-std::shared_ptr<msh::InputTargetListener> mir::DefaultServerConfiguration::the_input_target_listener()
2054-{
2055- return input_target_listener(
2056- [&]() -> std::shared_ptr<msh::InputTargetListener>
2057- {
2058- if (the_options()->get("enable-input", enable_input_default))
2059- return std::make_shared<mia::DispatcherController>(the_input_configuration());
2060- else
2061- return std::make_shared<mi::NullInputTargetListener>();
2062+std::shared_ptr<msh::InputTargeter> mir::DefaultServerConfiguration::the_input_targeter()
2063+{
2064+ return input_targeter(
2065+ [&]() -> std::shared_ptr<msh::InputTargeter>
2066+ {
2067+ return the_input_configuration()->the_input_targeter();
2068+ });
2069+}
2070+
2071+std::shared_ptr<ms::InputRegistrar> mir::DefaultServerConfiguration::the_input_registrar()
2072+{
2073+ return input_registrar(
2074+ [&]() -> std::shared_ptr<ms::InputRegistrar>
2075+ {
2076+ return the_input_configuration()->the_input_registrar();
2077 });
2078 }
2079
2080
2081=== modified file 'src/server/frontend/session_mediator.cpp'
2082--- src/server/frontend/session_mediator.cpp 2013-05-22 00:44:25 +0000
2083+++ src/server/frontend/session_mediator.cpp 2013-05-30 19:33:26 +0000
2084@@ -40,7 +40,7 @@
2085
2086 namespace msh = mir::shell;
2087 namespace mf = mir::frontend;
2088-namespace mfd=mir::frontend::detail;
2089+namespace mfd = mir::frontend::detail;
2090
2091 mf::SessionMediator::SessionMediator(
2092 std::shared_ptr<frontend::Shell> const& shell,
2093
2094=== modified file 'src/server/input/CMakeLists.txt'
2095--- src/server/input/CMakeLists.txt 2013-05-28 17:15:21 +0000
2096+++ src/server/input/CMakeLists.txt 2013-05-30 19:33:26 +0000
2097@@ -2,6 +2,8 @@
2098 INPUT_SOURCES
2099
2100 event_filter_chain.cpp
2101+
2102+ null_input_configuration.cpp
2103 null_input_report.cpp
2104 )
2105
2106
2107=== modified file 'src/server/input/android/CMakeLists.txt'
2108--- src/server/input/android/CMakeLists.txt 2013-04-24 05:22:20 +0000
2109+++ src/server/input/android/CMakeLists.txt 2013-05-30 19:33:26 +0000
2110@@ -9,7 +9,9 @@
2111 ${CMAKE_CURRENT_SOURCE_DIR}/default_android_input_configuration.cpp
2112 ${CMAKE_CURRENT_SOURCE_DIR}/android_input_application_handle.cpp
2113 ${CMAKE_CURRENT_SOURCE_DIR}/android_input_window_handle.cpp
2114- ${CMAKE_CURRENT_SOURCE_DIR}/android_dispatcher_controller.cpp
2115+ ${CMAKE_CURRENT_SOURCE_DIR}/android_input_registrar.cpp
2116+ ${CMAKE_CURRENT_SOURCE_DIR}/android_input_targeter.cpp
2117+ ${CMAKE_CURRENT_SOURCE_DIR}/android_input_target_enumerator.cpp
2118 )
2119
2120 set(
2121
2122=== modified file 'src/server/input/android/android_input_application_handle.cpp'
2123--- src/server/input/android/android_input_application_handle.cpp 2013-04-24 05:22:20 +0000
2124+++ src/server/input/android/android_input_application_handle.cpp 2013-05-30 19:33:26 +0000
2125@@ -18,15 +18,15 @@
2126
2127 #include "android_input_application_handle.h"
2128
2129-#include "mir/input/session_target.h"
2130+#include "mir/input/surface_target.h"
2131
2132 #include <limits.h>
2133
2134 namespace mi = mir::input;
2135 namespace mia = mi::android;
2136
2137-mia::InputApplicationHandle::InputApplicationHandle(std::shared_ptr<mi::SessionTarget> const& session)
2138- : weak_session(session)
2139+mia::InputApplicationHandle::InputApplicationHandle(std::shared_ptr<mi::SurfaceTarget> const& surface)
2140+ : weak_surface(surface)
2141 {
2142 updateInfo();
2143 }
2144@@ -36,12 +36,12 @@
2145 if (mInfo == NULL)
2146 mInfo = new droidinput::InputApplicationInfo;
2147
2148- auto session = weak_session.lock();
2149- if (!session)
2150+ auto surface = weak_surface.lock();
2151+ if (!surface)
2152 return false;
2153
2154 mInfo->dispatchingTimeout = INT_MAX;
2155- mInfo->name = droidinput::String8(session->name().c_str());
2156+ mInfo->name = droidinput::String8(surface->name().c_str());
2157
2158 return true;
2159 }
2160
2161=== modified file 'src/server/input/android/android_input_application_handle.h'
2162--- src/server/input/android/android_input_application_handle.h 2013-04-24 05:22:20 +0000
2163+++ src/server/input/android/android_input_application_handle.h 2013-05-30 19:33:26 +0000
2164@@ -30,7 +30,7 @@
2165
2166 namespace input
2167 {
2168-class SessionTarget;
2169+class SurfaceTarget;
2170
2171 namespace android
2172 {
2173@@ -38,7 +38,7 @@
2174 class InputApplicationHandle : public droidinput::InputApplicationHandle
2175 {
2176 public:
2177- InputApplicationHandle(std::shared_ptr<input::SessionTarget> const& surface);
2178+ InputApplicationHandle(std::shared_ptr<input::SurfaceTarget> const& surface);
2179 ~InputApplicationHandle() {}
2180
2181 bool updateInfo();
2182@@ -48,7 +48,7 @@
2183 InputApplicationHandle& operator=(InputApplicationHandle const&) = delete;
2184
2185 private:
2186- std::weak_ptr<input::SessionTarget> weak_session;
2187+ std::weak_ptr<input::SurfaceTarget> weak_surface;
2188 };
2189
2190 }
2191
2192=== modified file 'src/server/input/android/android_input_manager.cpp'
2193--- src/server/input/android/android_input_manager.cpp 2013-05-13 09:35:44 +0000
2194+++ src/server/input/android/android_input_manager.cpp 2013-05-30 19:33:26 +0000
2195@@ -18,7 +18,6 @@
2196 */
2197
2198 #include "mir/graphics/viewable_area.h"
2199-#include "mir/input/session_target.h"
2200 #include "mir/input/surface_target.h"
2201
2202 #include "android_input_manager.h"
2203@@ -37,11 +36,14 @@
2204 namespace mi = mir::input;
2205 namespace mia = mi::android;
2206
2207-mia::InputManager::InputManager(std::shared_ptr<mia::InputConfiguration> const& config)
2208- : event_hub(config->the_event_hub()),
2209- dispatcher(config->the_dispatcher()),
2210- reader_thread(config->the_reader_thread()),
2211- dispatcher_thread(config->the_dispatcher_thread())
2212+mia::InputManager::InputManager(droidinput::sp<droidinput::EventHubInterface> const& event_hub,
2213+ droidinput::sp<droidinput::InputDispatcherInterface> const& dispatcher,
2214+ std::shared_ptr<InputThread> const& reader_thread,
2215+ std::shared_ptr<InputThread> const& dispatcher_thread)
2216+ : event_hub(event_hub),
2217+ dispatcher(dispatcher),
2218+ reader_thread(reader_thread),
2219+ dispatcher_thread(dispatcher_thread)
2220 {
2221 }
2222
2223
2224=== modified file 'src/server/input/android/android_input_manager.h'
2225--- src/server/input/android/android_input_manager.h 2013-04-24 05:22:20 +0000
2226+++ src/server/input/android/android_input_manager.h 2013-05-30 19:33:26 +0000
2227@@ -37,10 +37,6 @@
2228
2229 namespace mir
2230 {
2231-namespace graphics
2232-{
2233-class ViewableArea;
2234-}
2235
2236 namespace input
2237 {
2238@@ -49,7 +45,6 @@
2239 namespace android
2240 {
2241 class InputThread;
2242-class InputConfiguration;
2243
2244 /// Encapsulates an instance of the Android input stack, that is to say an EventHub tied
2245 /// to an InputReader tied to an InputDispatcher. Provides interfaces for controlling input
2246@@ -57,8 +52,10 @@
2247 class InputManager : public mir::input::InputManager
2248 {
2249 public:
2250- explicit InputManager(
2251- std::shared_ptr<InputConfiguration> const& input_configuration);
2252+ explicit InputManager(droidinput::sp<droidinput::EventHubInterface> const& event_hub,
2253+ droidinput::sp<droidinput::InputDispatcherInterface> const& dispatcher,
2254+ std::shared_ptr<InputThread> const& reader_thread,
2255+ std::shared_ptr<InputThread> const& dispatcher_thread);
2256 virtual ~InputManager();
2257
2258 void start();
2259
2260=== added file 'src/server/input/android/android_input_registrar.cpp'
2261--- src/server/input/android/android_input_registrar.cpp 1970-01-01 00:00:00 +0000
2262+++ src/server/input/android/android_input_registrar.cpp 2013-05-30 19:33:26 +0000
2263@@ -0,0 +1,78 @@
2264+/*
2265+ * Copyright © 2013 Canonical Ltd.
2266+ *
2267+ * This program is free software: you can redistribute it and/or modify it
2268+ * under the terms of the GNU General Public License version 3,
2269+ * as published by the Free Software Foundation.
2270+ *
2271+ * This program is distributed in the hope that it will be useful,
2272+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2273+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2274+ * GNU General Public License for more details.
2275+ *
2276+ * You should have received a copy of the GNU General Public License
2277+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2278+ *
2279+ * Authored by: Robert Carr <robert.carr@canonical.com>
2280+ */
2281+
2282+#include "android_input_registrar.h"
2283+
2284+#include "android_input_window_handle.h"
2285+#include "android_input_application_handle.h"
2286+
2287+#include <InputDispatcher.h>
2288+
2289+#include <boost/throw_exception.hpp>
2290+
2291+#include <stdexcept>
2292+#include <mutex>
2293+
2294+namespace mi = mir::input;
2295+namespace mia = mi::android;
2296+
2297+mia::InputRegistrar::InputRegistrar(droidinput::sp<droidinput::InputDispatcherInterface> const& input_dispatcher)
2298+ : input_dispatcher(input_dispatcher)
2299+{
2300+}
2301+
2302+mia::InputRegistrar::~InputRegistrar() noexcept(true)
2303+{
2304+}
2305+
2306+void mia::InputRegistrar::input_surface_opened(std::shared_ptr<input::SurfaceTarget> const& opened_surface)
2307+{
2308+ std::unique_lock<std::mutex> lock(handles_mutex);
2309+
2310+ // TODO: We don't have much use for InputApplicationHandle so we simply use one per surface.
2311+ // it is only used in droidinput for logging and determining application not responding (ANR),
2312+ // we determine ANR on a per surface basis. When we have time we should factor InputApplicationHandle out
2313+ // of the input stack (merging it's state with WindowHandle). ~racarr
2314+ if (window_handles.find(opened_surface) != window_handles.end())
2315+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was opened twice"));
2316+
2317+ auto application_handle = new mia::InputApplicationHandle(opened_surface);
2318+ droidinput::sp<droidinput::InputWindowHandle> window_handle = new mia::InputWindowHandle(application_handle, opened_surface);
2319+ input_dispatcher->registerInputChannel(window_handle->getInfo()->inputChannel, window_handle, false);
2320+
2321+ window_handles[opened_surface] = window_handle;
2322+}
2323+
2324+void mia::InputRegistrar::input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface)
2325+{
2326+ std::unique_lock<std::mutex> lock(handles_mutex);
2327+ auto it = window_handles.find(closed_surface);
2328+ if (it == window_handles.end())
2329+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was closed twice"));
2330+
2331+ input_dispatcher->unregisterInputChannel(it->second->getInfo()->inputChannel);
2332+ window_handles.erase(it);
2333+}
2334+
2335+droidinput::sp<droidinput::InputWindowHandle> mia::InputRegistrar::handle_for_surface(std::shared_ptr<input::SurfaceTarget const> const& surface)
2336+{
2337+ std::unique_lock<std::mutex> lock(handles_mutex);
2338+ if (window_handles.find(surface) == window_handles.end())
2339+ BOOST_THROW_EXCEPTION(std::logic_error("Requesting handle for an unregistered surface"));
2340+ return window_handles[surface];
2341+}
2342
2343=== added file 'src/server/input/android/android_input_registrar.h'
2344--- src/server/input/android/android_input_registrar.h 1970-01-01 00:00:00 +0000
2345+++ src/server/input/android/android_input_registrar.h 2013-05-30 19:33:26 +0000
2346@@ -0,0 +1,72 @@
2347+/*
2348+ * Copyright © 2013 Canonical Ltd.
2349+ *
2350+ * This program is free software: you can redistribute it and/or modify it
2351+ * under the terms of the GNU General Public License version 3,
2352+ * as published by the Free Software Foundation.
2353+ *
2354+ * This program is distributed in the hope that it will be useful,
2355+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2356+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2357+ * GNU General Public License for more details.
2358+ *
2359+ * You should have received a copy of the GNU General Public License
2360+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2361+ *
2362+ * Authored by: Robert Carr <robert.carr@canonical.com>
2363+ */
2364+
2365+#ifndef MIR_INPUT_ANDROID_REGISTRAR_H_
2366+#define MIR_INPUT_ANDROID_REGISTRAR_H_
2367+
2368+#include "android_window_handle_repository.h"
2369+
2370+#include "mir/surfaces/input_registrar.h"
2371+
2372+#include <utils/StrongPointer.h>
2373+
2374+#include <map>
2375+#include <mutex>
2376+
2377+namespace android
2378+{
2379+class InputDispatcherInterface;
2380+class InputWindowHandle;
2381+}
2382+
2383+namespace droidinput = android;
2384+
2385+namespace mir
2386+{
2387+namespace input
2388+{
2389+namespace android
2390+{
2391+class InputConfiguration;
2392+class InputTargeter;
2393+
2394+class InputRegistrar : public surfaces::InputRegistrar, public WindowHandleRepository
2395+{
2396+public:
2397+ explicit InputRegistrar(droidinput::sp<droidinput::InputDispatcherInterface> const& input_dispatcher);
2398+ virtual ~InputRegistrar() noexcept(true);
2399+
2400+ void input_surface_opened(std::shared_ptr<input::SurfaceTarget> const& opened_surface);
2401+ void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface);
2402+
2403+
2404+ virtual droidinput::sp<droidinput::InputWindowHandle> handle_for_surface(std::shared_ptr<input::SurfaceTarget const> const& surface);
2405+
2406+private:
2407+ droidinput::sp<droidinput::InputDispatcherInterface> const input_dispatcher;
2408+
2409+ std::map<std::shared_ptr<input::SurfaceTarget const>, droidinput::sp<droidinput::InputWindowHandle>> window_handles;
2410+
2411+ std::mutex handles_mutex;
2412+};
2413+
2414+}
2415+}
2416+} // namespace mir
2417+
2418+#endif // MIR_INPUT_ANDROID_REGISTRAR_H_
2419
2420=== added file 'src/server/input/android/android_input_target_enumerator.cpp'
2421--- src/server/input/android/android_input_target_enumerator.cpp 1970-01-01 00:00:00 +0000
2422+++ src/server/input/android/android_input_target_enumerator.cpp 2013-05-30 19:33:26 +0000
2423@@ -0,0 +1,49 @@
2424+/*
2425+ * Copyright © 2013 Canonical Ltd.
2426+ *
2427+ * This program is free software: you can redistribute it and/or modify it
2428+ * under the terms of the GNU General Public License version 3,
2429+ * as published by the Free Software Foundation.
2430+ *
2431+ * This program is distributed in the hope that it will be useful,
2432+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2433+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2434+ * GNU General Public License for more details.
2435+ *
2436+ * You should have received a copy of the GNU General Public License
2437+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2438+ *
2439+ * Authored by: Robert Carr <robert.carr@canonical.com>
2440+ */
2441+
2442+#include "android_input_target_enumerator.h"
2443+
2444+#include "android_window_handle_repository.h"
2445+
2446+#include "mir/input/input_targets.h"
2447+
2448+#include <InputWindow.h>
2449+
2450+namespace mi = mir::input;
2451+namespace mia = mi::android;
2452+
2453+mia::InputTargetEnumerator::InputTargetEnumerator(std::shared_ptr<mi::InputTargets> const& targets,
2454+ std::shared_ptr<mia::WindowHandleRepository> const& repository)
2455+ : targets(targets),
2456+ repository(repository)
2457+{
2458+}
2459+
2460+mia::InputTargetEnumerator::~InputTargetEnumerator() noexcept(true)
2461+{
2462+}
2463+
2464+void mia::InputTargetEnumerator::for_each(std::function<void(droidinput::sp<droidinput::InputWindowHandle> const&)> const& callback)
2465+{
2466+ auto t = targets.lock();
2467+ auto r = repository.lock();
2468+ t->for_each([&callback, &r, this](std::shared_ptr<mi::SurfaceTarget> const& target){
2469+ auto handle = r->handle_for_surface(target);
2470+ callback(handle);
2471+ });
2472+}
2473
2474=== added file 'src/server/input/android/android_input_target_enumerator.h'
2475--- src/server/input/android/android_input_target_enumerator.h 1970-01-01 00:00:00 +0000
2476+++ src/server/input/android/android_input_target_enumerator.h 2013-05-30 19:33:26 +0000
2477@@ -0,0 +1,67 @@
2478+/*
2479+ * Copyright © 2013 Canonical Ltd.
2480+ *
2481+ * This program is free software: you can redistribute it and/or modify it
2482+ * under the terms of the GNU General Public License version 3,
2483+ * as published by the Free Software Foundation.
2484+ *
2485+ * This program is distributed in the hope that it will be useful,
2486+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2487+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2488+ * GNU General Public License for more details.
2489+ *
2490+ * You should have received a copy of the GNU General Public License
2491+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2492+ *
2493+ * Authored by: Robert Carr <robert.carr@canonical.com>
2494+ */
2495+
2496+#ifndef MIR_INPUT_ANDROID_TARGET_ENUMERATOR_H_
2497+#define MIR_INPUT_ANDROID_TARGET_ENUMERATOR_H_
2498+
2499+#include <InputEnumerator.h>
2500+
2501+#include <utils/StrongPointer.h>
2502+
2503+#include <memory>
2504+#include <functional>
2505+
2506+namespace android
2507+{
2508+class InputWindowHandle;
2509+}
2510+
2511+namespace droidinput = android;
2512+
2513+namespace mir
2514+{
2515+namespace surfaces
2516+{
2517+class InputRegitrar;
2518+}
2519+namespace input
2520+{
2521+class InputTargets;
2522+namespace android
2523+{
2524+class WindowHandleRepository;
2525+
2526+class InputTargetEnumerator : public droidinput::InputEnumerator
2527+{
2528+public:
2529+ explicit InputTargetEnumerator(std::shared_ptr<input::InputTargets> const& targets,
2530+ std::shared_ptr<WindowHandleRepository> const& repository);
2531+ virtual ~InputTargetEnumerator() noexcept(true);
2532+
2533+ void for_each(std::function<void(droidinput::sp<droidinput::InputWindowHandle> const&)> const& callback);
2534+
2535+private:
2536+ std::weak_ptr<input::InputTargets> const targets;
2537+ std::weak_ptr<input::android::WindowHandleRepository> const repository;
2538+};
2539+
2540+}
2541+}
2542+} // namespace mir
2543+
2544+#endif // MIR_INPUT_ANDROID_TARGET_ENUMERATOR_H_
2545
2546=== renamed file 'src/server/input/android/android_dispatcher_controller.cpp' => 'src/server/input/android/android_input_targeter.cpp'
2547--- src/server/input/android/android_dispatcher_controller.cpp 2013-05-02 00:11:18 +0000
2548+++ src/server/input/android/android_input_targeter.cpp 2013-05-30 19:33:26 +0000
2549@@ -16,13 +16,12 @@
2550 * Authored by: Robert Carr <robert.carr@canonical.com>
2551 */
2552
2553-#include "android_dispatcher_controller.h"
2554+#include "android_input_targeter.h"
2555+#include "android_input_registrar.h"
2556
2557 #include "android_input_window_handle.h"
2558 #include "android_input_application_handle.h"
2559
2560-#include "mir/input/android/android_input_configuration.h"
2561-
2562 #include <InputDispatcher.h>
2563
2564 #include <boost/throw_exception.hpp>
2565@@ -32,78 +31,28 @@
2566
2567 namespace mi = mir::input;
2568 namespace mia = mi::android;
2569-
2570-mia::DispatcherController::DispatcherController(std::shared_ptr<mia::InputConfiguration> const& config) :
2571- input_dispatcher(config->the_dispatcher())
2572-{
2573-}
2574-
2575-void mia::DispatcherController::input_application_opened(std::shared_ptr<mi::SessionTarget> const& session)
2576-{
2577- std::unique_lock<std::mutex> lock(handles_mutex);
2578- if (application_handles.find(session) != application_handles.end())
2579- BOOST_THROW_EXCEPTION(std::logic_error("An application was opened twice"));
2580- application_handles[session] = new mia::InputApplicationHandle(session);
2581-}
2582-
2583-void mia::DispatcherController::input_application_closed(std::shared_ptr<mi::SessionTarget> const& session)
2584-{
2585- std::unique_lock<std::mutex> lock(handles_mutex);
2586- if (application_handles.find(session) == application_handles.end())
2587- BOOST_THROW_EXCEPTION(std::logic_error("An application was closed twice"));
2588- application_handles.erase(session);
2589-}
2590-
2591-void mia::DispatcherController::input_surface_opened(std::shared_ptr<mi::SessionTarget> const& session,
2592- std::shared_ptr<input::SurfaceTarget> const& opened_surface)
2593-{
2594- std::unique_lock<std::mutex> lock(handles_mutex);
2595- auto application_handle = application_handles.find(session);
2596- if (application_handle == application_handles.end())
2597- BOOST_THROW_EXCEPTION(std::logic_error("A surface was opened for an unopened application"));
2598- if (window_handles.find(opened_surface) != window_handles.end())
2599- BOOST_THROW_EXCEPTION(std::logic_error("A surface was opened twice"));
2600-
2601- droidinput::sp<droidinput::InputWindowHandle> window_handle = new mia::InputWindowHandle(application_handle->second, opened_surface);
2602- input_dispatcher->registerInputChannel(window_handle->getInfo()->inputChannel, window_handle, false);
2603-
2604- window_handles[opened_surface] = window_handle;
2605-}
2606-
2607-void mia::DispatcherController::input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface)
2608-{
2609- std::unique_lock<std::mutex> lock(handles_mutex);
2610- auto it = window_handles.find(closed_surface);
2611- if (it == window_handles.end())
2612- BOOST_THROW_EXCEPTION(std::logic_error("A surface was closed twice"));
2613-
2614- input_dispatcher->unregisterInputChannel(it->second->getInfo()->inputChannel);
2615- window_handles.erase(it);
2616-}
2617-
2618-void mia::DispatcherController::focus_cleared()
2619-{
2620- droidinput::Vector<droidinput::sp<droidinput::InputWindowHandle>> empty_windows;
2621- droidinput::sp<droidinput::InputApplicationHandle> null_application = nullptr;
2622-
2623- input_dispatcher->setFocusedApplication(null_application);
2624- input_dispatcher->setInputWindows(empty_windows);
2625-}
2626-
2627-void mia::DispatcherController::focus_changed(std::shared_ptr<mi::SurfaceTarget> const& surface)
2628-{
2629- std::unique_lock<std::mutex> lock(handles_mutex);
2630-
2631- auto window_handle = window_handles[surface];
2632-
2633- if (!window_handle.get())
2634- BOOST_THROW_EXCEPTION(std::logic_error("Focus changed to an unopened surface"));
2635- auto application_handle = window_handle->inputApplicationHandle;
2636-
2637- input_dispatcher->setFocusedApplication(application_handle);
2638-
2639- droidinput::Vector<droidinput::sp<droidinput::InputWindowHandle>> windows;
2640- windows.push_back(window_handle);
2641-
2642- input_dispatcher->setInputWindows(windows);
2643+namespace ms = mir::surfaces;
2644+
2645+mia::InputTargeter::InputTargeter(droidinput::sp<droidinput::InputDispatcherInterface> const& input_dispatcher,
2646+ std::shared_ptr<mia::WindowHandleRepository> const& repository) :
2647+ input_dispatcher(input_dispatcher),
2648+ repository(repository)
2649+{
2650+}
2651+
2652+void mia::InputTargeter::focus_cleared()
2653+{
2654+ droidinput::sp<droidinput::InputWindowHandle> null_window = nullptr;
2655+
2656+ input_dispatcher->setKeyboardFocus(null_window);
2657+}
2658+
2659+void mia::InputTargeter::focus_changed(std::shared_ptr<mi::SurfaceTarget const> const& surface)
2660+{
2661+ auto window_handle = repository->handle_for_surface(surface);
2662+
2663+ if (window_handle == NULL)
2664+ BOOST_THROW_EXCEPTION(std::logic_error("Attempt to set keyboard focus to an unregistered surface"));
2665+
2666+ input_dispatcher->setKeyboardFocus(window_handle);
2667 }
2668
2669=== renamed file 'src/server/input/android/android_dispatcher_controller.h' => 'src/server/input/android/android_input_targeter.h'
2670--- src/server/input/android/android_dispatcher_controller.h 2013-05-02 00:11:18 +0000
2671+++ src/server/input/android/android_input_targeter.h 2013-05-30 19:33:26 +0000
2672@@ -16,10 +16,10 @@
2673 * Authored by: Robert Carr <robert.carr@canonical.com>
2674 */
2675
2676-#ifndef MIR_INPUT_ANDROID_DISPATCHER_CONTROLLER_H_
2677-#define MIR_INPUT_ANDROID_DISPATCHER_CONTROLLER_H_
2678+#ifndef MIR_INPUT_ANDROID_TARGET_H_
2679+#define MIR_INPUT_ANDROID_TARGET_H_
2680
2681-#include "mir/shell/input_target_listener.h"
2682+#include "mir/shell/input_targeter.h"
2683
2684 #include <utils/StrongPointer.h>
2685
2686@@ -30,7 +30,6 @@
2687 {
2688 class InputDispatcherInterface;
2689 class InputWindowHandle;
2690-class InputApplicationHandle;
2691 }
2692
2693 namespace droidinput = android;
2694@@ -42,38 +41,30 @@
2695 namespace android
2696 {
2697 class InputConfiguration;
2698+class WindowHandleRepository;
2699
2700-class DispatcherController : public shell::InputTargetListener
2701+class InputTargeter : public shell::InputTargeter
2702 {
2703 public:
2704- explicit DispatcherController(std::shared_ptr<InputConfiguration> const& input_configuration);
2705- virtual ~DispatcherController() noexcept(true) {}
2706+ explicit InputTargeter(droidinput::sp<droidinput::InputDispatcherInterface> const& input_dispatcher,
2707+ std::shared_ptr<WindowHandleRepository> const& repository);
2708+ virtual ~InputTargeter() noexcept(true) {}
2709
2710- void input_application_opened(std::shared_ptr<input::SessionTarget> const& application);
2711- void input_application_closed(std::shared_ptr<input::SessionTarget> const& application);
2712-
2713- void input_surface_opened(std::shared_ptr<input::SessionTarget> const& application,
2714- std::shared_ptr<input::SurfaceTarget> const& opened_surface);
2715- void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface);
2716-
2717- void focus_changed(std::shared_ptr<input::SurfaceTarget> const& focus_surface);
2718+ void focus_changed(std::shared_ptr<input::SurfaceTarget const> const& focus_surface);
2719 void focus_cleared();
2720
2721 protected:
2722- DispatcherController(const DispatcherController&) = delete;
2723- DispatcherController& operator=(const DispatcherController&) = delete;
2724+ InputTargeter(const InputTargeter&) = delete;
2725+ InputTargeter& operator=(const InputTargeter&) = delete;
2726
2727 private:
2728 droidinput::sp<droidinput::InputDispatcherInterface> input_dispatcher;
2729
2730- std::map<std::shared_ptr<input::SessionTarget>, droidinput::sp<droidinput::InputApplicationHandle>> application_handles;
2731- std::map<std::shared_ptr<input::SurfaceTarget>, droidinput::sp<droidinput::InputWindowHandle>> window_handles;
2732-
2733- std::mutex handles_mutex;
2734+ std::shared_ptr<WindowHandleRepository> const repository;
2735 };
2736
2737 }
2738 }
2739 } // namespace mir
2740
2741-#endif // MIR_INPUT_ANDROID_DISPATCHER_CONTROLLER_H_
2742+#endif // MIR_INPUT_ANDROID_TARGET_H_
2743
2744=== added file 'src/server/input/android/android_window_handle_repository.h'
2745--- src/server/input/android/android_window_handle_repository.h 1970-01-01 00:00:00 +0000
2746+++ src/server/input/android/android_window_handle_repository.h 2013-05-30 19:33:26 +0000
2747@@ -0,0 +1,59 @@
2748+/*
2749+ * Copyright © 2013 Canonical Ltd.
2750+ *
2751+ * This program is free software: you can redistribute it and/or modify it
2752+ * under the terms of the GNU General Public License version 3,
2753+ * as published by the Free Software Foundation.
2754+ *
2755+ * This program is distributed in the hope that it will be useful,
2756+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2757+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2758+ * GNU General Public License for more details.
2759+ *
2760+ * You should have received a copy of the GNU General Public License
2761+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2762+ *
2763+ * Authored by: Robert Carr <robert.carr@canonical.com>
2764+ */
2765+
2766+#ifndef MIR_INPUT_ANDROID_WINDOW_HANDLE_REPOSITORY_H_
2767+#define MIR_INPUT_ANDROID_WINDOW_HANDLE_REPOSITORY_H_
2768+
2769+#include <utils/StrongPointer.h>
2770+
2771+#include <memory>
2772+
2773+namespace android
2774+{
2775+class InputWindowHandle;
2776+}
2777+
2778+namespace droidinput = android;
2779+
2780+namespace mir
2781+{
2782+namespace input
2783+{
2784+class SurfaceTarget;
2785+namespace android
2786+{
2787+
2788+/// Interface internal to mir::input::android used for tracking the assosciation between droidinput::InputWindowHandle
2789+/// and mir::input::SurfaceTarget
2790+class WindowHandleRepository
2791+{
2792+public:
2793+ virtual ~WindowHandleRepository() = default;
2794+
2795+ virtual droidinput::sp<droidinput::InputWindowHandle> handle_for_surface(std::shared_ptr<input::SurfaceTarget const> const& surface) = 0;
2796+protected:
2797+ WindowHandleRepository() = default;
2798+ WindowHandleRepository(const WindowHandleRepository&) = delete;
2799+ WindowHandleRepository& operator=(const WindowHandleRepository&) = delete;
2800+};
2801+
2802+}
2803+}
2804+} // namespace mir
2805+
2806+#endif // MIR_INPUT_ANDROID_WINDOW_HANDLE_REPOSITORY_H_
2807
2808=== modified file 'src/server/input/android/default_android_input_configuration.cpp'
2809--- src/server/input/android/default_android_input_configuration.cpp 2013-05-28 17:47:03 +0000
2810+++ src/server/input/android/default_android_input_configuration.cpp 2013-05-30 19:33:26 +0000
2811@@ -20,6 +20,10 @@
2812 #include "event_filter_dispatcher_policy.h"
2813 #include "android_input_reader_policy.h"
2814 #include "android_input_thread.h"
2815+#include "android_input_registrar.h"
2816+#include "android_input_targeter.h"
2817+#include "android_input_target_enumerator.h"
2818+#include "android_input_manager.h"
2819 #include "../event_filter_chain.h"
2820
2821 #include <EventHub.h>
2822@@ -33,6 +37,8 @@
2823 namespace mi = mir::input;
2824 namespace mia = mi::android;
2825 namespace mg = mir::graphics;
2826+namespace ms = mir::surfaces;
2827+namespace msh = mir::shell;
2828
2829 namespace
2830 {
2831@@ -107,7 +113,7 @@
2832 droidinput::sp<droidinput::InputDispatcherInterface> mia::DefaultInputConfiguration::the_dispatcher()
2833 {
2834 return dispatcher(
2835- [this]()
2836+ [this]() -> droidinput::sp<droidinput::InputDispatcherInterface>
2837 {
2838 return new droidinput::InputDispatcher(the_dispatcher_policy(), input_report);
2839 });
2840@@ -152,7 +158,49 @@
2841 });
2842 }
2843
2844+std::shared_ptr<ms::InputRegistrar> mia::DefaultInputConfiguration::the_input_registrar()
2845+{
2846+ return input_registrar(
2847+ [this]()
2848+ {
2849+ return std::make_shared<mia::InputRegistrar>(the_dispatcher());
2850+ });
2851+}
2852+
2853+std::shared_ptr<mia::WindowHandleRepository> mia::DefaultInputConfiguration::the_window_handle_repository()
2854+{
2855+ return input_registrar(
2856+ [this]()
2857+ {
2858+ return std::make_shared<mia::InputRegistrar>(the_dispatcher());
2859+ });
2860+}
2861+
2862+std::shared_ptr<msh::InputTargeter> mia::DefaultInputConfiguration::the_input_targeter()
2863+{
2864+ return input_targeter(
2865+ [this]()
2866+ {
2867+ return std::make_shared<mia::InputTargeter>(the_dispatcher(), the_window_handle_repository());
2868+ });
2869+}
2870+
2871+std::shared_ptr<mi::InputManager> mia::DefaultInputConfiguration::the_input_manager()
2872+{
2873+ return input_manager(
2874+ [this]()
2875+ {
2876+ return std::make_shared<mia::InputManager>(the_event_hub(), the_dispatcher(),
2877+ the_reader_thread(), the_dispatcher_thread());
2878+ });
2879+}
2880+
2881 bool mia::DefaultInputConfiguration::is_key_repeat_enabled()
2882 {
2883 return true;
2884 }
2885+
2886+void mia::DefaultInputConfiguration::set_input_targets(std::shared_ptr<mi::InputTargets> const& targets)
2887+{
2888+ the_dispatcher()->setInputEnumerator(new mia::InputTargetEnumerator(targets, the_window_handle_repository()));
2889+}
2890
2891=== modified file 'src/server/input/android/default_android_input_configuration.h'
2892--- src/server/input/android/default_android_input_configuration.h 2013-05-28 17:15:21 +0000
2893+++ src/server/input/android/default_android_input_configuration.h 2013-05-30 19:33:26 +0000
2894@@ -19,7 +19,7 @@
2895 #ifndef MIR_INPUT_ANDROID_DEFAULT_ANDROID_INPUT_CONFIGURATION_H_
2896 #define MIR_INPUT_ANDROID_DEFAULT_ANDROID_INPUT_CONFIGURATION_H_
2897
2898-#include "mir/input/android/android_input_configuration.h"
2899+#include "mir/input/input_configuration.h"
2900
2901 #include "mir/cached_ptr.h"
2902
2903@@ -35,6 +35,8 @@
2904 class InputReaderInterface;
2905 class InputReaderPolicyInterface;
2906 class InputDispatcherPolicyInterface;
2907+class InputDispatcherInterface;
2908+class EventHubInterface;
2909 }
2910
2911 namespace mir
2912@@ -43,6 +45,10 @@
2913 {
2914 class ViewableArea;
2915 }
2916+namespace shell
2917+{
2918+class InputTargeter;
2919+}
2920 namespace input
2921 {
2922 class EventFilter;
2923@@ -52,8 +58,11 @@
2924
2925 namespace android
2926 {
2927+class InputRegistrar;
2928+class WindowHandleRepository;
2929+class InputThread;
2930
2931-class DefaultInputConfiguration : public InputConfiguration
2932+class DefaultInputConfiguration : public input::InputConfiguration
2933 {
2934 public:
2935 DefaultInputConfiguration(std::initializer_list<std::shared_ptr<EventFilter> const> const& filters,
2936@@ -62,22 +71,29 @@
2937 std::shared_ptr<input::InputReport> const& input_report);
2938 virtual ~DefaultInputConfiguration();
2939
2940- droidinput::sp<droidinput::EventHubInterface> the_event_hub();
2941- droidinput::sp<droidinput::InputDispatcherInterface> the_dispatcher();
2942- droidinput::sp<droidinput::InputReaderInterface> the_reader();
2943-
2944- std::shared_ptr<InputThread> the_dispatcher_thread();
2945- std::shared_ptr<InputThread> the_reader_thread();
2946+ std::shared_ptr<surfaces::InputRegistrar> the_input_registrar();
2947+ std::shared_ptr<shell::InputTargeter> the_input_targeter();
2948+ std::shared_ptr<input::InputManager> the_input_manager();
2949+
2950+ void set_input_targets(std::shared_ptr<input::InputTargets> const& targets);
2951+
2952+ virtual bool is_key_repeat_enabled();
2953+
2954+protected:
2955+ virtual droidinput::sp<droidinput::EventHubInterface> the_event_hub();
2956+ virtual droidinput::sp<droidinput::InputDispatcherInterface> the_dispatcher();
2957+ virtual droidinput::sp<droidinput::InputReaderInterface> the_reader();
2958+
2959+ virtual std::shared_ptr<InputThread> the_dispatcher_thread();
2960+ virtual std::shared_ptr<InputThread> the_reader_thread();
2961
2962 virtual droidinput::sp<droidinput::InputDispatcherPolicyInterface> the_dispatcher_policy();
2963 virtual droidinput::sp<droidinput::InputReaderPolicyInterface> the_reader_policy();
2964-
2965- virtual bool is_key_repeat_enabled();
2966-
2967-protected:
2968+
2969+ std::shared_ptr<WindowHandleRepository> the_window_handle_repository();
2970+
2971 DefaultInputConfiguration(DefaultInputConfiguration const&) = delete;
2972 DefaultInputConfiguration& operator=(DefaultInputConfiguration const&) = delete;
2973-
2974 private:
2975 template <typename Type>
2976 class CachedAndroidPtr
2977@@ -104,10 +120,16 @@
2978 std::shared_ptr<EventFilterChain> const filter_chain;
2979 std::shared_ptr<graphics::ViewableArea> const view_area;
2980 std::shared_ptr<CursorListener> const cursor_listener;
2981+
2982 std::shared_ptr<input::InputReport> const input_report;
2983
2984 CachedPtr<InputThread> dispatcher_thread;
2985 CachedPtr<InputThread> reader_thread;
2986+ CachedPtr<InputRegistrar> input_registrar;
2987+
2988+ CachedPtr<shell::InputTargeter> input_targeter;
2989+ CachedPtr<input::InputManager> input_manager;
2990+
2991 CachedAndroidPtr<droidinput::EventHubInterface> event_hub;
2992 CachedAndroidPtr<droidinput::InputDispatcherPolicyInterface> dispatcher_policy;
2993 CachedAndroidPtr<droidinput::InputReaderPolicyInterface> reader_policy;
2994
2995=== added file 'src/server/input/null_input_configuration.cpp'
2996--- src/server/input/null_input_configuration.cpp 1970-01-01 00:00:00 +0000
2997+++ src/server/input/null_input_configuration.cpp 2013-05-30 19:33:26 +0000
2998@@ -0,0 +1,93 @@
2999+/*
3000+ * Copyright © 2013 Canonical Ltd.
3001+ *
3002+ * This program is free software: you can redistribute it and/or modify it
3003+ * under the terms of the GNU General Public License version 3,
3004+ * as published by the Free Software Foundation.
3005+ *
3006+ * This program is distributed in the hope that it will be useful,
3007+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3008+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3009+ * GNU General Public License for more details.
3010+ *
3011+ * You should have received a copy of the GNU General Public License
3012+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3013+ *
3014+ * Authored by: Robert Carr <robert.carr@canonical.com>
3015+ */
3016+
3017+#include "mir/input/null_input_configuration.h"
3018+
3019+#include "mir/surfaces/input_registrar.h"
3020+#include "mir/shell/input_targeter.h"
3021+#include "mir/input/input_manager.h"
3022+
3023+namespace mi = mir::input;
3024+namespace ms = mir::surfaces;
3025+namespace msh = mir::shell;
3026+
3027+namespace
3028+{
3029+
3030+struct NullInputRegistrar : public ms::InputRegistrar
3031+{
3032+ NullInputRegistrar() = default;
3033+ virtual ~NullInputRegistrar() noexcept(true) = default;
3034+
3035+ void input_surface_opened(std::shared_ptr<mi::SurfaceTarget> const&)
3036+ {
3037+ }
3038+
3039+ void input_surface_closed(std::shared_ptr<mi::SurfaceTarget> const&)
3040+ {
3041+ }
3042+};
3043+
3044+struct NullInputTargeter : public msh::InputTargeter
3045+{
3046+ NullInputTargeter() = default;
3047+ virtual ~NullInputTargeter() noexcept(true) = default;
3048+
3049+ void focus_changed(std::shared_ptr<mi::SurfaceTarget const> const&)
3050+ {
3051+ }
3052+
3053+ void focus_cleared()
3054+ {
3055+ }
3056+};
3057+
3058+struct NullInputManager : public mi::InputManager
3059+{
3060+ void start()
3061+ {
3062+ }
3063+ void stop()
3064+ {
3065+ }
3066+ std::shared_ptr<mi::InputChannel> make_input_channel()
3067+ {
3068+ return std::shared_ptr<mi::InputChannel>();
3069+ }
3070+};
3071+
3072+}
3073+
3074+std::shared_ptr<ms::InputRegistrar> mi::NullInputConfiguration::the_input_registrar()
3075+{
3076+ return std::make_shared<NullInputRegistrar>();
3077+}
3078+
3079+std::shared_ptr<msh::InputTargeter> mi::NullInputConfiguration::the_input_targeter()
3080+{
3081+ return std::make_shared<NullInputTargeter>();
3082+}
3083+
3084+std::shared_ptr<mi::InputManager> mi::NullInputConfiguration::the_input_manager()
3085+{
3086+ return std::make_shared<NullInputManager>();
3087+}
3088+
3089+void mi::NullInputConfiguration::set_input_targets(std::shared_ptr<mi::InputTargets> const&)
3090+{
3091+}
3092
3093=== modified file 'src/server/shell/application_session.cpp'
3094--- src/server/shell/application_session.cpp 2013-05-21 17:16:43 +0000
3095+++ src/server/shell/application_session.cpp 2013-05-30 19:33:26 +0000
3096@@ -19,7 +19,6 @@
3097 #include "mir/shell/application_session.h"
3098 #include "mir/shell/surface.h"
3099 #include "mir/shell/surface_factory.h"
3100-#include "mir/shell/input_target_listener.h"
3101
3102 #include <boost/throw_exception.hpp>
3103
3104@@ -34,11 +33,9 @@
3105
3106 msh::ApplicationSession::ApplicationSession(
3107 std::shared_ptr<SurfaceFactory> const& surface_factory,
3108- std::shared_ptr<msh::InputTargetListener> const& input_target_listener,
3109 std::string const& session_name,
3110 std::shared_ptr<me::EventSink> const& sink) :
3111 surface_factory(surface_factory),
3112- input_target_listener(input_target_listener),
3113 session_name(session_name),
3114 event_sink(sink),
3115 next_surface_id(0)
3116@@ -48,9 +45,8 @@
3117
3118 msh::ApplicationSession::ApplicationSession(
3119 std::shared_ptr<SurfaceFactory> const& surface_factory,
3120- std::shared_ptr<msh::InputTargetListener> const& input_target_listener,
3121 std::string const& session_name) :
3122- ApplicationSession(surface_factory, input_target_listener, session_name, std::shared_ptr<me::EventSink>())
3123+ ApplicationSession(surface_factory, session_name, std::shared_ptr<me::EventSink>())
3124 {
3125 }
3126
3127@@ -59,7 +55,6 @@
3128 std::unique_lock<std::mutex> lock(surfaces_mutex);
3129 for (auto const& pair_id_surface : surfaces)
3130 {
3131- input_target_listener->input_surface_closed(pair_id_surface.second);
3132 pair_id_surface.second->destroy();
3133 }
3134 }
3135@@ -109,7 +104,6 @@
3136 std::unique_lock<std::mutex> lock(surfaces_mutex);
3137 auto p = checked_find(id);
3138
3139- input_target_listener->input_surface_closed(p->second);
3140 p->second->destroy();
3141 surfaces.erase(p);
3142 }
3143
3144=== modified file 'src/server/shell/session_manager.cpp'
3145--- src/server/shell/session_manager.cpp 2013-05-21 17:16:43 +0000
3146+++ src/server/shell/session_manager.cpp 2013-05-30 19:33:26 +0000
3147@@ -24,7 +24,6 @@
3148 #include "mir/shell/focus_setter.h"
3149 #include "mir/shell/session.h"
3150 #include "mir/shell/surface.h"
3151-#include "mir/shell/input_target_listener.h"
3152 #include "mir/shell/session_listener.h"
3153
3154 #include <memory>
3155@@ -38,20 +37,17 @@
3156 std::shared_ptr<msh::SessionContainer> const& container,
3157 std::shared_ptr<msh::FocusSequence> const& sequence,
3158 std::shared_ptr<msh::FocusSetter> const& focus_setter,
3159- std::shared_ptr<msh::InputTargetListener> const& input_target_listener,
3160 std::shared_ptr<msh::SessionListener> const& session_listener) :
3161 surface_factory(surface_factory),
3162 app_container(container),
3163 focus_sequence(sequence),
3164 focus_setter(focus_setter),
3165- input_target_listener(input_target_listener),
3166 session_listener(session_listener)
3167 {
3168 assert(surface_factory);
3169 assert(sequence);
3170 assert(container);
3171 assert(focus_setter);
3172- assert(input_target_listener);
3173 assert(session_listener);
3174 }
3175
3176@@ -60,7 +56,7 @@
3177 /*
3178 * Close all open sessions. We need to do this manually here
3179 * to break the cyclic dependency between msh::Session
3180- * and msh::InputTargetListener, since our implementations
3181+ * and mi::*, since our implementations
3182 * of these interfaces keep strong references to each other.
3183 * TODO: Investigate other solutions (e.g. weak_ptr)
3184 */
3185@@ -79,11 +75,10 @@
3186 std::string const& name,
3187 std::shared_ptr<events::EventSink> const& sink)
3188 {
3189- std::shared_ptr<msh::Session> new_session = std::make_shared<msh::ApplicationSession>(surface_factory, input_target_listener, name, sink);
3190+ std::shared_ptr<msh::Session> new_session = std::make_shared<msh::ApplicationSession>(surface_factory, name, sink);
3191
3192 app_container->insert_session(new_session);
3193
3194- input_target_listener->input_application_opened(new_session);
3195 session_listener->starting(new_session);
3196
3197 set_focus_to_locked(std::unique_lock<std::mutex>(mutex), new_session);
3198@@ -97,18 +92,12 @@
3199
3200 focus_application = shell_session;
3201 focus_setter->set_focus_to(shell_session);
3202-
3203- if (shell_session && shell_session->default_surface())
3204- input_target_listener->focus_changed(shell_session->default_surface());
3205- else if (shell_session == old_focus || !shell_session)
3206- input_target_listener->focus_cleared();
3207 }
3208
3209 void msh::SessionManager::close_session(std::shared_ptr<mf::Session> const& session)
3210 {
3211 auto shell_session = std::dynamic_pointer_cast<Session>(session);
3212
3213- input_target_listener->input_application_closed(shell_session);
3214 session_listener->stopping(shell_session);
3215
3216 app_container->remove_session(shell_session);
3217@@ -145,8 +134,6 @@
3218 auto shell_session = std::dynamic_pointer_cast<Session>(session);
3219 auto id = shell_session->create_surface(params);
3220
3221- input_target_listener->input_surface_opened(shell_session,
3222- std::dynamic_pointer_cast<msh::Surface>(shell_session->get_surface(id)));
3223 set_focus_to_locked(std::unique_lock<std::mutex>(mutex), shell_session);
3224
3225 return id;
3226
3227=== modified file 'src/server/shell/single_visibility_focus_mechanism.cpp'
3228--- src/server/shell/single_visibility_focus_mechanism.cpp 2013-05-02 00:11:18 +0000
3229+++ src/server/shell/single_visibility_focus_mechanism.cpp 2013-05-30 19:33:26 +0000
3230@@ -16,27 +16,36 @@
3231 * Authored By: Robert Carr <robert.carr@canonical.com>
3232 */
3233
3234+#include "mir/frontend/session.h"
3235 #include "mir/shell/session_container.h"
3236-#include "mir/frontend/session.h"
3237 #include "mir/shell/single_visibility_focus_mechanism.h"
3238-
3239+#include "mir/shell/input_targeter.h"
3240 #include "mir/shell/session.h"
3241 #include "mir/shell/surface.h"
3242
3243 namespace mf = mir::frontend;
3244 namespace msh = mir::shell;
3245
3246-msh::SingleVisibilityFocusMechanism::SingleVisibilityFocusMechanism(std::shared_ptr<msh::SessionContainer> const& app_container)
3247- : app_container(app_container)
3248+msh::SingleVisibilityFocusMechanism::SingleVisibilityFocusMechanism(std::shared_ptr<msh::SessionContainer> const& app_container,
3249+ std::shared_ptr<msh::InputTargeter> const& input_targeter)
3250+ : app_container(app_container),
3251+ input_targeter(input_targeter)
3252 {
3253 }
3254
3255 void msh::SingleVisibilityFocusMechanism::set_focus_to(std::shared_ptr<Session> const& focus_session)
3256 {
3257+ bool set_input_focus = false;
3258 app_container->for_each(
3259 [&](std::shared_ptr<mf::Session> const& session) {
3260 if (session == focus_session)
3261 {
3262+ auto surface = focus_session->default_surface();
3263+ if (surface)
3264+ {
3265+ surface->take_input_focus(input_targeter);
3266+ set_input_focus = true;
3267+ }
3268 session->show();
3269 }
3270 else
3271@@ -44,4 +53,7 @@
3272 session->hide();
3273 }
3274 });
3275+
3276+ if (set_input_focus == false)
3277+ input_targeter->focus_cleared();
3278 }
3279
3280=== modified file 'src/server/shell/surface.cpp'
3281--- src/server/shell/surface.cpp 2013-05-21 17:16:43 +0000
3282+++ src/server/shell/surface.cpp 2013-05-30 19:33:26 +0000
3283@@ -18,9 +18,11 @@
3284
3285 #include "mir/shell/surface.h"
3286 #include "mir/shell/surface_builder.h"
3287+#include "mir/shell/input_targeter.h"
3288 #include "mir/input/input_channel.h"
3289+#include "mir/events/event_sink.h"
3290+
3291 #include "mir_toolkit/event.h"
3292-#include "mir/events/event_sink.h"
3293
3294 #include <boost/throw_exception.hpp>
3295
3296@@ -30,15 +32,14 @@
3297 namespace msh = mir::shell;
3298 namespace mc = mir::compositor;
3299 namespace mi = mir::input;
3300+namespace ms = mir::surfaces;
3301
3302 msh::Surface::Surface(
3303 std::shared_ptr<SurfaceBuilder> const& builder,
3304 shell::SurfaceCreationParameters const& params,
3305- std::shared_ptr<input::InputChannel> const& input_channel,
3306 frontend::SurfaceId id,
3307 std::shared_ptr<events::EventSink> const& sink)
3308 : builder(builder),
3309- input_channel(input_channel),
3310 surface(builder->create_surface(params)),
3311 id(id),
3312 event_sink(sink),
3313@@ -49,10 +50,8 @@
3314
3315 msh::Surface::Surface(
3316 std::shared_ptr<SurfaceBuilder> const& builder,
3317- shell::SurfaceCreationParameters const& params,
3318- std::shared_ptr<input::InputChannel> const& input_channel)
3319+ shell::SurfaceCreationParameters const& params)
3320 : builder(builder),
3321- input_channel(input_channel),
3322 surface(builder->create_surface(params)),
3323 id(),
3324 event_sink(),
3325@@ -168,23 +167,38 @@
3326
3327 bool msh::Surface::supports_input() const
3328 {
3329- if (input_channel)
3330- return true;
3331- return false;
3332+ if (auto const& s = surface.lock())
3333+ {
3334+ return s->supports_input();
3335+ }
3336+ else
3337+ {
3338+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
3339+ }
3340 }
3341
3342 int msh::Surface::client_input_fd() const
3343 {
3344- if (!supports_input())
3345- BOOST_THROW_EXCEPTION(std::logic_error("Surface does not support input"));
3346- return input_channel->client_fd();
3347+ if (auto const& s = surface.lock())
3348+ {
3349+ return s->client_input_fd();
3350+ }
3351+ else
3352+ {
3353+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
3354+ }
3355 }
3356
3357 int msh::Surface::server_input_fd() const
3358 {
3359- if (!supports_input())
3360- BOOST_THROW_EXCEPTION(std::logic_error("Surface does not support input"));
3361- return input_channel->server_fd();
3362+ if (auto const& s = surface.lock())
3363+ {
3364+ return s->server_input_fd();
3365+ }
3366+ else
3367+ {
3368+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
3369+ }
3370 }
3371
3372 int msh::Surface::configure(MirSurfaceAttrib attrib, int value)
3373@@ -276,3 +290,12 @@
3374 event_sink->handle_event(e);
3375 }
3376 }
3377+
3378+void msh::Surface::take_input_focus(std::shared_ptr<msh::InputTargeter> const& targeter)
3379+{
3380+ auto s = surface.lock();
3381+ if (s)
3382+ targeter->focus_changed(s);
3383+ else
3384+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
3385+}
3386
3387=== modified file 'src/server/shell/surface_source.cpp'
3388--- src/server/shell/surface_source.cpp 2013-05-21 17:16:43 +0000
3389+++ src/server/shell/surface_source.cpp 2013-05-30 19:33:26 +0000
3390@@ -30,11 +30,8 @@
3391 namespace mf = mir::frontend;
3392
3393
3394-msh::SurfaceSource::SurfaceSource(
3395- std::shared_ptr<SurfaceBuilder> const& surface_builder,
3396- std::shared_ptr<mi::InputChannelFactory> const& input_factory) :
3397- surface_builder(surface_builder),
3398- input_factory(input_factory)
3399+msh::SurfaceSource::SurfaceSource(std::shared_ptr<SurfaceBuilder> const& surface_builder)
3400+ : surface_builder(surface_builder)
3401 {
3402 assert(surface_builder);
3403 }
3404@@ -47,7 +44,6 @@
3405 return std::make_shared<Surface>(
3406 surface_builder,
3407 params,
3408- input_factory->make_input_channel(),
3409 id,
3410 sink);
3411 }
3412
3413=== modified file 'src/server/surfaces/surface.cpp'
3414--- src/server/surfaces/surface.cpp 2013-05-22 00:44:25 +0000
3415+++ src/server/surfaces/surface.cpp 2013-05-30 19:33:26 +0000
3416@@ -20,23 +20,31 @@
3417
3418 #include "mir/surfaces/surface.h"
3419 #include "mir/surfaces/buffer_bundle.h"
3420-
3421+#include "mir/input/input_channel.h"
3422+
3423+#include <boost/throw_exception.hpp>
3424+
3425+#include <stdexcept>
3426 #include <cassert>
3427+
3428 #include <glm/gtc/matrix_transform.hpp>
3429
3430 namespace mc = mir::compositor;
3431 namespace ms = mir::surfaces;
3432 namespace mg = mir::graphics;
3433+namespace mi = mir::input;
3434 namespace geom = mir::geometry;
3435
3436 ms::Surface::Surface(
3437 std::string const& name,
3438 geom::Point const& top_left,
3439 std::shared_ptr<BufferBundle> buffer_bundle,
3440+ std::shared_ptr<input::InputChannel> const& input_channel,
3441 std::function<void()> const& change_callback) :
3442 surface_name(name),
3443 top_left_point(top_left),
3444 buffer_bundle(buffer_bundle),
3445+ input_channel(input_channel),
3446 client_buffer_resource(buffer_bundle->secure_client_buffer()),
3447 alpha_value(1.0f),
3448 is_hidden(false),
3449@@ -173,3 +181,24 @@
3450 {
3451 buffer_is_valid = true;
3452 }
3453+
3454+bool ms::Surface::supports_input() const
3455+{
3456+ if (input_channel)
3457+ return true;
3458+ return false;
3459+}
3460+
3461+int ms::Surface::client_input_fd() const
3462+{
3463+ if (!supports_input())
3464+ BOOST_THROW_EXCEPTION(std::logic_error("Surface does not support input"));
3465+ return input_channel->client_fd();
3466+}
3467+
3468+int ms::Surface::server_input_fd() const
3469+{
3470+ if (!supports_input())
3471+ BOOST_THROW_EXCEPTION(std::logic_error("Surface does not support input"));
3472+ return input_channel->server_fd();
3473+}
3474
3475=== modified file 'src/server/surfaces/surface_stack.cpp'
3476--- src/server/surfaces/surface_stack.cpp 2013-05-21 17:16:43 +0000
3477+++ src/server/surfaces/surface_stack.cpp 2013-05-30 19:33:26 +0000
3478@@ -24,6 +24,8 @@
3479 #include "mir/shell/surface_creation_parameters.h"
3480 #include "mir/surfaces/surface.h"
3481 #include "mir/surfaces/surface_stack.h"
3482+#include "mir/surfaces/input_registrar.h"
3483+#include "mir/input/input_channel_factory.h"
3484
3485 #include <algorithm>
3486 #include <cassert>
3487@@ -33,10 +35,15 @@
3488 namespace ms = mir::surfaces;
3489 namespace mc = mir::compositor;
3490 namespace mg = mir::graphics;
3491+namespace mi = mir::input;
3492 namespace geom = mir::geometry;
3493
3494-ms::SurfaceStack::SurfaceStack(std::shared_ptr<BufferBundleFactory> const& bb_factory)
3495+ms::SurfaceStack::SurfaceStack(std::shared_ptr<BufferBundleFactory> const& bb_factory,
3496+ std::shared_ptr<mi::InputChannelFactory> const& input_factory,
3497+ std::shared_ptr<ms::InputRegistrar> const& input_registrar)
3498 : buffer_bundle_factory{bb_factory},
3499+ input_factory{input_factory},
3500+ input_registrar{input_registrar},
3501 notify_change{[]{}}
3502 {
3503 assert(buffer_bundle_factory);
3504@@ -70,6 +77,7 @@
3505 new ms::Surface(
3506 params.name, params.top_left,
3507 buffer_bundle_factory->create_buffer_bundle(buffer_properties),
3508+ input_factory->make_input_channel(),
3509 [this]() { emit_change_notification(); }));
3510
3511 {
3512@@ -77,6 +85,10 @@
3513 surfaces.push_back(surface);
3514 }
3515
3516+ // TODO: It might be a nice refactoring to combine this with input channel creation
3517+ // i.e. client_fd = registrar->register_for_input(surface). ~racarr
3518+ input_registrar->input_surface_opened(surface);
3519+
3520 emit_change_notification();
3521
3522 return surface;
3523@@ -88,8 +100,12 @@
3524 std::lock_guard<std::mutex> lg(guard);
3525
3526 auto const p = std::find(surfaces.begin(), surfaces.end(), surface.lock());
3527-
3528- if (p != surfaces.end()) surfaces.erase(p);
3529+
3530+ if (p != surfaces.end())
3531+ {
3532+ input_registrar->input_surface_closed(*p);
3533+ surfaces.erase(p);
3534+ }
3535 // else; TODO error logging
3536 }
3537
3538@@ -101,3 +117,9 @@
3539 std::lock_guard<std::mutex> lock{notify_change_mutex};
3540 notify_change();
3541 }
3542+
3543+void ms::SurfaceStack::for_each(std::function<void(std::shared_ptr<mi::SurfaceTarget> const&)> const& callback)
3544+{
3545+ for (auto it = surfaces.rbegin(); it != surfaces.rend(); ++it)
3546+ callback(*it);
3547+}
3548
3549=== modified file 'src/shared/input/android/android_input_receiver.cpp'
3550--- src/shared/input/android/android_input_receiver.cpp 2013-05-17 19:42:09 +0000
3551+++ src/shared/input/android/android_input_receiver.cpp 2013-05-30 19:33:26 +0000
3552@@ -71,14 +71,29 @@
3553
3554 }
3555
3556+bool mircva::InputReceiver::try_next_event(MirEvent &ev)
3557+{
3558+ droidinput::InputEvent *android_event;
3559+ uint32_t event_sequence_id;
3560+
3561+ if(input_consumer->consume(&event_factory, true,
3562+ -1, &event_sequence_id, &android_event) != droidinput::WOULD_BLOCK)
3563+ {
3564+ mia::Lexicon::translate(android_event, ev);
3565+
3566+ map_key_event(xkb_mapper, ev);
3567+
3568+ input_consumer->sendFinishedSignal(event_sequence_id, true);
3569+
3570+ return true;
3571+ }
3572+ return false;
3573+}
3574+
3575 // TODO: We use a droidinput::Looper here for polling functionality but it might be nice to integrate
3576 // with the existing client io_service ~racarr ~tvoss
3577 bool mircva::InputReceiver::next_event(std::chrono::milliseconds const& timeout, MirEvent &ev)
3578 {
3579- droidinput::InputEvent *android_event;
3580- uint32_t event_sequence_id;
3581- bool handled_event = false;
3582-
3583 if (!fd_added)
3584 {
3585 // TODO: Why will this fail from the constructor? ~racarr
3586@@ -86,27 +101,16 @@
3587 fd_added = true;
3588 }
3589
3590+ if(try_next_event(ev))
3591+ return true;
3592+
3593 auto result = looper->pollOnce(timeout.count());
3594 if (result == ALOOPER_POLL_WAKE)
3595 return false;
3596- else if (result == ALOOPER_POLL_ERROR) // TODO: Exception?
3597- return false;
3598-
3599- if(input_consumer->consume(&event_factory, true,
3600- -1, &event_sequence_id, &android_event) != droidinput::WOULD_BLOCK)
3601- {
3602- mia::Lexicon::translate(android_event, ev);
3603-
3604- map_key_event(xkb_mapper, ev);
3605-
3606- input_consumer->sendFinishedSignal(event_sequence_id, true);
3607- handled_event = true;
3608- }
3609-
3610- // So far once we have sent an event to the client there is no chance for redispatch
3611- // so the client handles all events.
3612-
3613- return handled_event;
3614+ if (result == ALOOPER_POLL_ERROR) // TODO: Exception?
3615+ return false;
3616+
3617+ return try_next_event(ev);
3618 }
3619
3620 void mircva::InputReceiver::wake()
3621
3622=== modified file 'src/shared/input/android/android_input_receiver.h'
3623--- src/shared/input/android/android_input_receiver.h 2013-05-13 23:20:52 +0000
3624+++ src/shared/input/android/android_input_receiver.h 2013-05-30 19:33:26 +0000
3625@@ -78,6 +78,8 @@
3626 bool fd_added;
3627
3628 std::shared_ptr<XKBMapper> xkb_mapper;
3629+
3630+ bool try_next_event(MirEvent &ev);
3631 };
3632
3633 }
3634
3635=== modified file 'tests/acceptance-tests/test_client_input.cpp'
3636--- tests/acceptance-tests/test_client_input.cpp 2013-05-28 17:15:21 +0000
3637+++ tests/acceptance-tests/test_client_input.cpp 2013-05-30 19:33:26 +0000
3638@@ -17,9 +17,12 @@
3639 */
3640
3641 #include "mir/graphics/display.h"
3642+#include "mir/graphics/viewable_area.h"
3643+#include "mir/shell/surface_creation_parameters.h"
3644+#include "mir/shell/placement_strategy.h"
3645
3646 #include "src/server/input/android/android_input_manager.h"
3647-#include "src/server/input/android/android_dispatcher_controller.h"
3648+#include "src/server/input/android/android_input_targeter.h"
3649
3650 #include "mir_toolkit/mir_client_library.h"
3651
3652@@ -38,11 +41,16 @@
3653
3654 #include <thread>
3655 #include <functional>
3656+#include <map>
3657
3658 namespace mi = mir::input;
3659 namespace mia = mi::android;
3660 namespace mis = mi::synthesis;
3661+namespace mf = mir::frontend;
3662 namespace msh = mir::shell;
3663+namespace ms = mir::surfaces;
3664+namespace mg = mir::graphics;
3665+namespace geom = mir::geometry;
3666 namespace mt = mir::test;
3667 namespace mtd = mt::doubles;
3668 namespace mtf = mir_test_framework;
3669@@ -52,30 +60,36 @@
3670 char const* const mir_test_socket = mtf::test_socket_file().c_str();
3671 }
3672
3673+#include "mir/input/surface_target.h"
3674+
3675 namespace
3676 {
3677-
3678-struct FocusNotifyingDispatcherController : public mia::DispatcherController
3679+struct FocusNotifyingInputTargeter : public msh::InputTargeter
3680 {
3681- FocusNotifyingDispatcherController(std::shared_ptr<mia::InputConfiguration> const& configuration,
3682- mt::WaitCondition &wait_condition)
3683- : DispatcherController(configuration),
3684- on_focus_set(wait_condition)
3685+ FocusNotifyingInputTargeter(std::shared_ptr<msh::InputTargeter> const& real_targeter,
3686+ std::function<void(void)> const& focus_set)
3687+ : real_targeter(real_targeter),
3688+ focus_set(focus_set)
3689 {
3690
3691 }
3692+ virtual ~FocusNotifyingInputTargeter() noexcept(true) {}
3693
3694- void focus_changed(std::shared_ptr<mi::SurfaceTarget> const& surface) override
3695+ void focus_changed(std::shared_ptr<mi::SurfaceTarget const> const& surface) override
3696 {
3697- DispatcherController::focus_changed(surface);
3698-
3699+ real_targeter->focus_changed(surface);
3700+
3701 // We need a synchronization primitive inorder to halt test event injection
3702 // until after a surface has taken focus (lest the events be discarded).
3703- if (surface)
3704- on_focus_set.wake_up_everyone();
3705+ focus_set();
3706+ }
3707+ void focus_cleared()
3708+ {
3709+ real_targeter->focus_cleared();
3710 }
3711
3712- mt::WaitCondition &on_focus_set;
3713+ std::shared_ptr<msh::InputTargeter> const real_targeter;
3714+ std::function<void(void)> focus_set;
3715 };
3716
3717 struct FakeInputServerConfiguration : public mir_test_framework::TestingServerConfiguration
3718@@ -85,57 +99,41 @@
3719 {
3720 }
3721
3722- virtual void inject_input()
3723- {
3724- }
3725-
3726- void exec() override
3727- {
3728- input_injection_thread = std::thread([this]() -> void
3729- {
3730- on_focus_set.wait_for_at_most_seconds(10);
3731- fake_event_hub->synthesize_builtin_keyboard_added();
3732- fake_event_hub->synthesize_builtin_cursor_added();
3733- fake_event_hub->synthesize_device_scan_complete();
3734- inject_input();
3735- });
3736- }
3737-
3738- void on_exit() override
3739- {
3740- input_injection_thread.join();
3741- }
3742-
3743- std::shared_ptr<mia::InputConfiguration> the_input_configuration() override
3744+ virtual void inject_input_after_focus()
3745+ {
3746+ }
3747+
3748+ std::shared_ptr<mi::InputConfiguration> the_input_configuration() override
3749 {
3750 fake_event_hub = input_config.the_fake_event_hub();
3751+ fake_event_hub->synthesize_builtin_keyboard_added();
3752+ fake_event_hub->synthesize_builtin_cursor_added();
3753+ fake_event_hub->synthesize_device_scan_complete();
3754+
3755 return mt::fake_shared(input_config);
3756 }
3757
3758 std::shared_ptr<mi::InputManager> the_input_manager() override
3759 {
3760- return input_manager(
3761- [&]()
3762- {
3763- // Force usage of real input even in case of tests-use-real-input = false.
3764- return std::make_shared<mia::InputManager>(the_input_configuration());
3765- });
3766+ return DefaultServerConfiguration::the_input_manager();
3767+ }
3768+ std::shared_ptr<ms::InputRegistrar> the_input_registrar() override
3769+ {
3770+ return DefaultServerConfiguration::the_input_registrar();
3771 }
3772
3773- std::shared_ptr<msh::InputTargetListener>
3774- the_input_target_listener() override
3775+ std::shared_ptr<msh::InputTargeter>
3776+ the_input_targeter() override
3777 {
3778- return input_target_listener(
3779+ return input_targeter(
3780 [this]()
3781 {
3782- return std::make_shared<FocusNotifyingDispatcherController>(mt::fake_shared(input_config), on_focus_set);
3783+ return std::make_shared<FocusNotifyingInputTargeter>(DefaultServerConfiguration::the_input_targeter(), std::bind(std::mem_fn(&FakeInputServerConfiguration::inject_input_after_focus), this));
3784 });
3785 }
3786
3787 mtd::FakeEventHubInputConfiguration input_config;
3788 mia::FakeEventHub* fake_event_hub;
3789- mt::WaitCondition on_focus_set;
3790- std::thread input_injection_thread;
3791 };
3792
3793
3794@@ -201,6 +199,7 @@
3795 static void handle_input(MirSurface* /* surface */, MirEvent const* ev, void* context)
3796 {
3797 auto client = static_cast<InputReceivingClient *>(context);
3798+
3799 if (client->handler->handle_input(ev))
3800 {
3801 client->event_received[client->events_received].wake_up_everyone();
3802@@ -210,6 +209,18 @@
3803 virtual void expect_input()
3804 {
3805 }
3806+
3807+ virtual MirSurfaceParameters parameters()
3808+ {
3809+ MirSurfaceParameters const request_params =
3810+ {
3811+ __PRETTY_FUNCTION__,
3812+ surface_width, surface_height,
3813+ mir_pixel_format_abgr_8888,
3814+ mir_buffer_usage_hardware
3815+ };
3816+ return request_params;
3817+ }
3818
3819 void exec()
3820 {
3821@@ -223,18 +234,13 @@
3822 connection_callback,
3823 this));
3824 ASSERT_TRUE(connection != NULL);
3825- MirSurfaceParameters const request_params =
3826- {
3827- __PRETTY_FUNCTION__,
3828- surface_width, surface_height,
3829- mir_pixel_format_abgr_8888,
3830- mir_buffer_usage_hardware
3831- };
3832+
3833 MirEventDelegate const event_delegate =
3834 {
3835 handle_input,
3836 this
3837 };
3838+ auto request_params = parameters();
3839 mir_wait_for(mir_connection_create_surface(connection, &request_params, create_surface_callback, this));
3840
3841 mir_surface_set_event_handler(surface, &event_delegate);
3842@@ -253,7 +259,7 @@
3843 }
3844
3845 std::shared_ptr<MockInputHandler> handler;
3846- static int const max_events_to_receive = 3;
3847+ static int const max_events_to_receive = 4;
3848 mt::WaitCondition event_received[max_events_to_receive];
3849
3850 int events_to_receive;
3851@@ -288,6 +294,15 @@
3852
3853 return true;
3854 }
3855+MATCHER(HoverExitEvent, "")
3856+{
3857+ if (arg->type != mir_event_type_motion)
3858+ return false;
3859+ if (arg->motion.action != mir_motion_action_hover_exit)
3860+ return false;
3861+
3862+ return true;
3863+}
3864
3865 MATCHER_P2(ButtonDownEvent, x, y, "")
3866 {
3867@@ -308,6 +323,9 @@
3868 {
3869 if (arg->type != mir_event_type_motion)
3870 return false;
3871+ if (arg->motion.action != mir_motion_action_move &&
3872+ arg->motion.action != mir_motion_action_hover_move)
3873+ return false;
3874 if (arg->motion.pointer_coordinates[0].x != x)
3875 return false;
3876 if (arg->motion.pointer_coordinates[0].y != y)
3877@@ -328,7 +346,7 @@
3878
3879 struct InputProducingServerConfiguration : FakeInputServerConfiguration
3880 {
3881- void inject_input()
3882+ void inject_input_after_focus()
3883 {
3884 // We send multiple events in order to verify the client is handling them
3885 // and server dispatch does not become backed up.
3886@@ -358,7 +376,7 @@
3887
3888 struct InputProducingServerConfiguration : FakeInputServerConfiguration
3889 {
3890- void inject_input()
3891+ void inject_input_after_focus()
3892 {
3893 fake_event_hub->synthesize_event(mis::a_key_down_event()
3894 .of_scancode(KEY_LEFTSHIFT));
3895@@ -394,7 +412,7 @@
3896
3897 struct InputProducingServerConfiguration : FakeInputServerConfiguration
3898 {
3899- void inject_input()
3900+ void inject_input_after_focus()
3901 {
3902 fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(InputReceivingClient::surface_width,
3903 InputReceivingClient::surface_height));
3904@@ -430,7 +448,7 @@
3905
3906 struct InputProducingServerConfiguration : FakeInputServerConfiguration
3907 {
3908- void inject_input()
3909+ void inject_input_after_focus()
3910 {
3911 fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
3912 }
3913@@ -453,3 +471,165 @@
3914 } client_config;
3915 launch_client_process(client_config);
3916 }
3917+
3918+namespace
3919+{
3920+struct StubViewableArea : public mg::ViewableArea
3921+{
3922+ StubViewableArea(int width, int height) :
3923+ width(width),
3924+ height(height),
3925+ x(0),
3926+ y(0)
3927+ {
3928+ }
3929+
3930+ geom::Rectangle view_area() const
3931+ {
3932+ return geom::Rectangle{geom::Point{x, y},
3933+ geom::Size{width, height}};
3934+ }
3935+
3936+ geom::Width const width;
3937+ geom::Height const height;
3938+ geom::X const x;
3939+ geom::Y const y;
3940+};
3941+
3942+typedef std::map<std::string, geom::Point> PositionList;
3943+
3944+struct StaticPlacementStrategy : public msh::PlacementStrategy
3945+{
3946+ StaticPlacementStrategy(PositionList positions)
3947+ : surface_positions_by_name(positions)
3948+ {
3949+ }
3950+
3951+ msh::SurfaceCreationParameters place(msh::SurfaceCreationParameters const& request_parameters)
3952+ {
3953+ auto placed = request_parameters;
3954+ placed.top_left = surface_positions_by_name[request_parameters.name];
3955+ return placed;
3956+ }
3957+ PositionList surface_positions_by_name;
3958+};
3959+
3960+}
3961+
3962+TEST_F(TestClientInput, multiple_clients_receive_motion_inside_windows)
3963+{
3964+ using namespace ::testing;
3965+
3966+ int const screen_width = 1000;
3967+ int const screen_height = 800;
3968+ int const client_width = screen_width/2;
3969+ int const client_height = screen_height;
3970+ std::string const surface1_name = "1";
3971+ std::string const surface2_name = "2";
3972+
3973+ PositionList positions;
3974+ positions[surface1_name] = geom::Point{geom::X{0}, geom::Y{0}};
3975+ positions[surface2_name] = geom::Point{geom::X{screen_width/2}, geom::Y{0}};
3976+
3977+ struct TestServerConfiguration : FakeInputServerConfiguration
3978+ {
3979+ TestServerConfiguration(int screen_width, int screen_height, PositionList positions)
3980+ : screen_width(screen_width),
3981+ screen_height(screen_height),
3982+ positions(positions),
3983+ clients_ready(0)
3984+ {
3985+ }
3986+
3987+ std::shared_ptr<mg::ViewableArea> the_viewable_area() override
3988+ {
3989+ return std::make_shared<StubViewableArea>(screen_width, screen_height);
3990+ }
3991+ std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy() override
3992+ {
3993+ return std::make_shared<StaticPlacementStrategy>(positions);
3994+ }
3995+
3996+ void inject_input_after_focus() override
3997+ {
3998+ clients_ready++;
3999+ if (clients_ready != 2) // We wait until both clients have connected and registered with the input stack.
4000+ return;
4001+
4002+ // In the bounds of the first surface
4003+ fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2-1, 0));
4004+ // In the bounds of the second surface
4005+ fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2, 0));
4006+ }
4007+ int screen_width, screen_height;
4008+ PositionList positions;
4009+
4010+ int clients_ready;
4011+ } server_config(screen_width, screen_height, positions);
4012+
4013+ launch_server_process(server_config);
4014+
4015+ MirSurfaceParameters const surface1_params =
4016+ {
4017+ surface1_name.c_str(),
4018+ client_width, client_height,
4019+ mir_pixel_format_abgr_8888,
4020+ mir_buffer_usage_hardware
4021+ };
4022+ MirSurfaceParameters const surface2_params =
4023+ {
4024+ surface2_name.c_str(),
4025+ client_width, client_height,
4026+ mir_pixel_format_abgr_8888,
4027+ mir_buffer_usage_hardware
4028+ };
4029+ struct ParameterizedClient : InputReceivingClient
4030+ {
4031+ ParameterizedClient(MirSurfaceParameters params, int events_to_expect) :
4032+ InputReceivingClient(events_to_expect),
4033+ params(params)
4034+ {
4035+ }
4036+
4037+ MirSurfaceParameters parameters() override
4038+ {
4039+ return params;
4040+ }
4041+
4042+ MirSurfaceParameters params;
4043+ };
4044+ struct InputClientOne : ParameterizedClient
4045+ {
4046+ InputClientOne(MirSurfaceParameters params) :
4047+ ParameterizedClient(params, 3)
4048+ {
4049+ }
4050+
4051+ void expect_input() override
4052+ {
4053+ InSequence seq;
4054+ EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(1).WillOnce(Return(true));
4055+ EXPECT_CALL(*handler, handle_input(
4056+ MotionEventWithPosition(params.width - 1, 0))).Times(1).WillOnce(Return(true));
4057+ EXPECT_CALL(*handler, handle_input(HoverExitEvent())).Times(1).WillOnce(Return(true));
4058+ }
4059+ } client_1(surface1_params);
4060+ struct InputClientTwo : ParameterizedClient
4061+ {
4062+ InputClientTwo(MirSurfaceParameters params) :
4063+ ParameterizedClient(params, 2)
4064+ {
4065+ }
4066+
4067+ void expect_input() override
4068+ {
4069+ InSequence seq;
4070+ EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(1).WillOnce(Return(true));
4071+ EXPECT_CALL(*handler, handle_input(
4072+ MotionEventWithPosition(params.width - 1, 0))).Times(1).WillOnce(Return(true));
4073+ }
4074+ } client_2(surface2_params);
4075+
4076+ launch_client_process(client_1);
4077+ launch_client_process(client_2);
4078+}
4079
4080=== modified file 'tests/acceptance-tests/test_focus_selection.cpp'
4081--- tests/acceptance-tests/test_focus_selection.cpp 2013-05-02 00:11:18 +0000
4082+++ tests/acceptance-tests/test_focus_selection.cpp 2013-05-30 19:33:26 +0000
4083@@ -24,11 +24,11 @@
4084 #include "mir/shell/organising_surface_factory.h"
4085 #include "mir/shell/session_manager.h"
4086 #include "mir/graphics/display.h"
4087-#include "mir/shell/input_target_listener.h"
4088+#include "mir/shell/input_targeter.h"
4089
4090 #include "mir_test_framework/display_server_test_fixture.h"
4091 #include "mir_test_doubles/mock_focus_setter.h"
4092-#include "mir_test_doubles/mock_input_target_listener.h"
4093+#include "mir_test_doubles/mock_input_targeter.h"
4094
4095 #include <gtest/gtest.h>
4096 #include <gmock/gmock.h>
4097@@ -167,37 +167,33 @@
4098 {
4099 struct ServerConfig : TestingServerConfiguration
4100 {
4101- std::shared_ptr<mtd::MockInputTargetListener> target_listener;
4102+ std::shared_ptr<mtd::MockInputTargeter> targeter;
4103 bool expected;
4104
4105 ServerConfig()
4106- : target_listener(std::make_shared<mtd::MockInputTargetListener>()),
4107+ : targeter(std::make_shared<mtd::MockInputTargeter>()),
4108 expected(false)
4109 {
4110 }
4111
4112- std::shared_ptr<msh::InputTargetListener>
4113- the_input_target_listener() override
4114+ std::shared_ptr<msh::InputTargeter>
4115+ the_input_targeter() override
4116 {
4117 using namespace ::testing;
4118
4119 if (!expected)
4120 {
4121
4122- EXPECT_CALL(*target_listener, input_application_opened(_)).Times(AtLeast(0));
4123- EXPECT_CALL(*target_listener, input_application_closed(_)).Times(AtLeast(0));
4124- EXPECT_CALL(*target_listener, input_surface_opened(_,_)).Times(AtLeast(0));
4125- EXPECT_CALL(*target_listener, input_surface_closed(_)).Times(AtLeast(0));
4126- EXPECT_CALL(*target_listener, focus_cleared()).Times(AtLeast(0));
4127+ EXPECT_CALL(*targeter, focus_cleared()).Times(AtLeast(0));
4128
4129 {
4130 InSequence seq;
4131- EXPECT_CALL(*target_listener, focus_changed(NonNullSurfaceTarget())).Times(1);
4132+ EXPECT_CALL(*targeter, focus_changed(NonNullSurfaceTarget())).Times(1);
4133 expected = true;
4134 }
4135 }
4136
4137- return target_listener;
4138+ return targeter;
4139 }
4140 } server_config;
4141
4142
4143=== modified file 'tests/acceptance-tests/test_server_shutdown.cpp'
4144--- tests/acceptance-tests/test_server_shutdown.cpp 2013-05-28 17:15:21 +0000
4145+++ tests/acceptance-tests/test_server_shutdown.cpp 2013-05-30 19:33:26 +0000
4146@@ -197,7 +197,7 @@
4147 /* Use the real input manager, but with a fake event hub */
4148 struct ServerConfig : TestingServerConfiguration
4149 {
4150- std::shared_ptr<mia::InputConfiguration> the_input_configuration() override
4151+ std::shared_ptr<mi::InputConfiguration> the_input_configuration() override
4152 {
4153 if (!input_configuration)
4154 {
4155@@ -217,12 +217,16 @@
4156 return DefaultServerConfiguration::the_input_manager();
4157 }
4158
4159- std::shared_ptr<mir::shell::InputTargetListener> the_input_target_listener() override
4160- {
4161- return DefaultServerConfiguration::the_input_target_listener();
4162+ std::shared_ptr<mir::shell::InputTargeter> the_input_targeter() override
4163+ {
4164+ return DefaultServerConfiguration::the_input_targeter();
4165+ }
4166+ std::shared_ptr<mir::surfaces::InputRegistrar> the_input_registrar() override
4167+ {
4168+ return DefaultServerConfiguration::the_input_registrar();
4169 }
4170
4171- std::shared_ptr<mia::InputConfiguration> input_configuration;
4172+ std::shared_ptr<mi::InputConfiguration> input_configuration;
4173 };
4174
4175 auto server_config = std::make_shared<ServerConfig>();
4176
4177=== modified file 'tests/behavior-tests/session_management_context.cpp'
4178--- tests/behavior-tests/session_management_context.cpp 2013-05-21 17:16:43 +0000
4179+++ tests/behavior-tests/session_management_context.cpp 2013-05-30 19:33:26 +0000
4180@@ -25,7 +25,6 @@
4181 #include "mir/shell/single_visibility_focus_mechanism.h"
4182 #include "mir/shell/session_container.h"
4183 #include "mir/frontend/shell.h"
4184-#include "mir/input/input_channel.h"
4185 #include "mir/shell/surface_factory.h"
4186 #include "mir/graphics/display.h"
4187 #include "mir/default_server_configuration.h"
4188@@ -39,7 +38,6 @@
4189 namespace msh = mir::shell;
4190 namespace mg = mir::graphics;
4191 namespace mc = mir::compositor;
4192-namespace mi = mir::input;
4193 namespace geom = mir::geometry;
4194 namespace mt = mir::test;
4195 namespace mtc = mir::test::cucumber;
4196@@ -73,7 +71,6 @@
4197 return std::make_shared<msh::Surface>(
4198 mt::fake_shared(surface_builder),
4199 params,
4200- std::shared_ptr<mir::input::InputChannel>(),
4201 id,
4202 sink);
4203 }
4204
4205=== modified file 'tests/death-tests/test_application_manager_death.cpp'
4206--- tests/death-tests/test_application_manager_death.cpp 2013-05-02 00:11:18 +0000
4207+++ tests/death-tests/test_application_manager_death.cpp 2013-05-30 19:33:26 +0000
4208@@ -35,7 +35,6 @@
4209 std::shared_ptr<msh::SessionContainer>(),
4210 std::shared_ptr<msh::FocusSequence>(),
4211 std::shared_ptr<msh::FocusSetter>(),
4212- std::shared_ptr<msh::InputTargetListener>(),
4213 std::shared_ptr<msh::SessionListener>()),
4214 ::testing::KilledBySignal(SIGABRT),
4215 ".*");
4216
4217=== modified file 'tests/integration-tests/graphics/android/test_internal_client.cpp'
4218--- tests/integration-tests/graphics/android/test_internal_client.cpp 2013-05-21 17:16:43 +0000
4219+++ tests/integration-tests/graphics/android/test_internal_client.cpp 2013-05-30 19:33:26 +0000
4220@@ -35,6 +35,8 @@
4221 #include "mir/frontend/surface_id.h"
4222 #include "mir/input/input_channel_factory.h"
4223
4224+#include "mir_test_doubles/stub_input_registrar.h"
4225+
4226 #include <EGL/egl.h>
4227 #include <gtest/gtest.h>
4228
4229@@ -49,6 +51,7 @@
4230 namespace msh=mir::shell;
4231 namespace mf=mir::frontend;
4232 namespace mi=mir::input;
4233+namespace mtd=mir::test::doubles;
4234
4235 namespace
4236 {
4237@@ -82,13 +85,14 @@
4238 auto id = mf::SurfaceId{4458};
4239
4240 auto stub_input_factory = std::make_shared<StubInputFactory>();
4241+ auto stub_input_registrar = std::make_shared<mtd::StubInputRegistrar>();
4242 auto null_buffer_initializer = std::make_shared<mg::NullBufferInitializer>();
4243 auto allocator = std::make_shared<mga::AndroidGraphicBufferAllocator>(null_buffer_initializer);
4244 auto strategy = std::make_shared<mc::SwapperFactory>(allocator);
4245 auto buffer_bundle_factory = std::make_shared<mc::BufferBundleManager>(strategy);
4246- auto ss = std::make_shared<ms::SurfaceStack>(buffer_bundle_factory);
4247+ auto ss = std::make_shared<ms::SurfaceStack>(buffer_bundle_factory, stub_input_factory, stub_input_registrar);
4248 auto surface_controller = std::make_shared<ms::SurfaceController>(ss);
4249- auto surface_source = std::make_shared<msh::SurfaceSource>(surface_controller, stub_input_factory);
4250+ auto surface_source = std::make_shared<msh::SurfaceSource>(surface_controller);
4251 auto mir_surface = surface_source->create_surface(params, id, std::shared_ptr<mir::events::EventSink>());
4252
4253 auto report = std::shared_ptr<mg::NullDisplayReport>();
4254
4255=== modified file 'tests/integration-tests/input/android/CMakeLists.txt'
4256--- tests/integration-tests/input/android/CMakeLists.txt 2013-04-24 05:22:20 +0000
4257+++ tests/integration-tests/input/android/CMakeLists.txt 2013-05-30 19:33:26 +0000
4258@@ -1,6 +1,5 @@
4259 list(
4260 APPEND INTEGRATION_TESTS_SRCS
4261- ${CMAKE_CURRENT_SOURCE_DIR}/test_fake_event_hub_to_event_filter.cpp
4262 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_manager.cpp
4263 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_cursor_listener.cpp
4264 )
4265
4266=== modified file 'tests/integration-tests/input/android/test_android_cursor_listener.cpp'
4267--- tests/integration-tests/input/android/test_android_cursor_listener.cpp 2013-05-28 17:15:21 +0000
4268+++ tests/integration-tests/input/android/test_android_cursor_listener.cpp 2013-05-30 19:33:26 +0000
4269@@ -17,10 +17,11 @@
4270 * Daniel d'Andrada <daniel.dandrada@canonical.com>
4271 */
4272
4273-#include "mir/input/event_filter.h"
4274 #include "src/server/input/android/android_input_manager.h"
4275 #include "src/server/input/android/default_android_input_configuration.h"
4276+#include "mir/input/event_filter.h"
4277 #include "mir/input/cursor_listener.h"
4278+#include "mir/input/input_targets.h"
4279 #include "mir/input/null_input_report.h"
4280
4281 #include "mir_test/fake_shared.h"
4282@@ -50,6 +51,13 @@
4283 {
4284 using namespace ::testing;
4285
4286+struct StubInputTargets : public mi::InputTargets
4287+{
4288+ void for_each(std::function<void(std::shared_ptr<mi::SurfaceTarget> const&)> const&)
4289+ {
4290+ }
4291+};
4292+
4293 struct MockCursorListener : public mi::CursorListener
4294 {
4295 MOCK_METHOD2(cursor_moved_to, void(float, float));
4296@@ -79,7 +87,10 @@
4297
4298 fake_event_hub = configuration->the_fake_event_hub();
4299
4300- input_manager = std::make_shared<mia::InputManager>(configuration);
4301+ input_manager = configuration->the_input_manager();
4302+
4303+ stub_targets = std::make_shared<StubInputTargets>();
4304+ configuration->set_input_targets(stub_targets);
4305
4306 input_manager->start();
4307 }
4308@@ -93,8 +104,9 @@
4309 mia::FakeEventHub* fake_event_hub;
4310 std::shared_ptr<MockEventFilter> event_filter;
4311 NiceMock<mtd::MockViewableArea> viewable_area;
4312- std::shared_ptr<mia::InputManager> input_manager;
4313+ std::shared_ptr<mi::InputManager> input_manager;
4314 MockCursorListener cursor_listener;
4315+ std::shared_ptr<StubInputTargets> stub_targets;
4316 };
4317
4318 }
4319
4320=== modified file 'tests/integration-tests/input/android/test_android_input_manager.cpp'
4321--- tests/integration-tests/input/android/test_android_input_manager.cpp 2013-05-28 17:15:21 +0000
4322+++ tests/integration-tests/input/android/test_android_input_manager.cpp 2013-05-30 19:33:26 +0000
4323@@ -18,13 +18,13 @@
4324 */
4325
4326 #include "mir/input/event_filter.h"
4327+#include "mir/input/input_targets.h"
4328 #include "mir/shell/surface_creation_parameters.h"
4329-#include "mir/input/android/android_input_configuration.h"
4330 #include "mir/input/null_input_report.h"
4331
4332-#include "src/server/input/android/default_android_input_configuration.h"
4333 #include "src/server/input/android/android_input_manager.h"
4334-#include "src/server/input/android/android_dispatcher_controller.h"
4335+#include "src/server/input/android/android_input_targeter.h"
4336+#include "src/server/input/android/android_input_registrar.h"
4337 #include "src/server/input/android/event_filter_dispatcher_policy.h"
4338
4339 #include "mir_test/fake_shared.h"
4340@@ -32,7 +32,6 @@
4341 #include "mir_test/fake_event_hub_input_configuration.h"
4342 #include "mir_test_doubles/mock_event_filter.h"
4343 #include "mir_test_doubles/mock_viewable_area.h"
4344-#include "mir_test_doubles/stub_session_target.h"
4345 #include "mir_test_doubles/stub_surface_target.h"
4346 #include "mir_test/wait_condition.h"
4347 #include "mir_test/event_factory.h"
4348@@ -40,6 +39,7 @@
4349
4350 #include <EventHub.h>
4351 #include <InputDispatcher.h>
4352+#include <InputEnumerator.h>
4353
4354 #include <gmock/gmock.h>
4355 #include <gtest/gtest.h>
4356@@ -51,6 +51,7 @@
4357 namespace mia = mir::input::android;
4358 namespace mis = mir::input::synthesis;
4359 namespace mg = mir::graphics;
4360+namespace ms = mir::surfaces;
4361 namespace msh = mir::shell;
4362 namespace geom = mir::geometry;
4363 namespace mt = mir::test;
4364@@ -68,6 +69,13 @@
4365
4366 static const std::shared_ptr<mi::CursorListener> null_cursor_listener{};
4367
4368+struct StubInputTargets : public mi::InputTargets
4369+{
4370+ void for_each(std::function<void(std::shared_ptr<mi::SurfaceTarget> const&)> const&)
4371+ {
4372+ }
4373+};
4374+
4375 class AndroidInputManagerAndEventFilterDispatcherSetup : public testing::Test
4376 {
4377 public:
4378@@ -79,8 +87,11 @@
4379 .WillByDefault(Return(default_view_area));
4380
4381 fake_event_hub = configuration->the_fake_event_hub();
4382+
4383+ input_manager = configuration->the_input_manager();
4384
4385- input_manager = std::make_shared<mia::InputManager>(configuration);
4386+ stub_targets = std::make_shared<StubInputTargets>();
4387+ configuration->set_input_targets(stub_targets);
4388
4389 input_manager->start();
4390 }
4391@@ -93,9 +104,10 @@
4392 protected:
4393 std::shared_ptr<mtd::FakeEventHubInputConfiguration> configuration;
4394 mia::FakeEventHub* fake_event_hub;
4395- std::shared_ptr<mia::InputManager> input_manager;
4396+ std::shared_ptr<mi::InputManager> input_manager;
4397 std::shared_ptr<MockEventFilter> event_filter;
4398 NiceMock<mtd::MockViewableArea> viewable_area;
4399+ std::shared_ptr<StubInputTargets> stub_targets;
4400 };
4401
4402 }
4403@@ -249,11 +261,15 @@
4404
4405 ON_CALL(viewable_area, view_area())
4406 .WillByDefault(Return(default_view_area));
4407- input_manager = std::make_shared<mia::InputManager>(configuration);
4408- input_target_listener = std::make_shared<mia::DispatcherController>(configuration);
4409+ input_manager = configuration->the_input_manager();
4410+
4411+ input_registrar = configuration->the_input_registrar();
4412+ input_targeter = configuration->the_input_targeter();
4413
4414 dispatcher_policy = configuration->the_mock_dispatcher_policy();
4415
4416+ stub_targets = std::make_shared<StubInputTargets>();
4417+ configuration->set_input_targets(stub_targets);
4418 }
4419
4420 ~AndroidInputManagerDispatcherInterceptSetup()
4421@@ -283,8 +299,11 @@
4422 mia::FakeEventHub* fake_event_hub;
4423 droidinput::sp<MockDispatcherPolicy> dispatcher_policy;
4424
4425- std::shared_ptr<mia::InputManager> input_manager;
4426- std::shared_ptr<msh::InputTargetListener> input_target_listener;
4427+ std::shared_ptr<StubInputTargets> stub_targets;
4428+
4429+ std::shared_ptr<mi::InputManager> input_manager;
4430+ std::shared_ptr<ms::InputRegistrar> input_registrar;
4431+ std::shared_ptr<msh::InputTargeter> input_targeter;
4432 };
4433
4434 MATCHER_P(WindowHandleWithInputFd, input_fd, "")
4435@@ -302,8 +321,6 @@
4436
4437 mt::WaitCondition wait_condition;
4438
4439- mtd::StubSessionTarget session;
4440-
4441 auto input_fd = test_fd();
4442 mtd::StubSurfaceTarget surface(input_fd);
4443
4444@@ -312,9 +329,8 @@
4445 EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd), _, _))
4446 .Times(1).WillOnce(DoAll(mt::WakeUp(&wait_condition), Return(-1)));
4447
4448- input_target_listener->input_application_opened(mt::fake_shared(session));
4449- input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface));
4450- input_target_listener->focus_changed(mt::fake_shared(surface));
4451+ input_registrar->input_surface_opened(mt::fake_shared(surface));
4452+ input_targeter->focus_changed(mt::fake_shared(surface));
4453
4454 fake_event_hub->synthesize_builtin_keyboard_added();
4455 fake_event_hub->synthesize_device_scan_complete();
4456@@ -330,16 +346,13 @@
4457
4458 mt::WaitCondition wait1, wait2, wait3;
4459
4460- mtd::StubSessionTarget session;
4461-
4462 auto input_fd_1 = test_fd();
4463 mtd::StubSurfaceTarget surface1(input_fd_1);
4464 auto input_fd_2 = test_fd();
4465 mtd::StubSurfaceTarget surface2(input_fd_2);
4466
4467- input_target_listener->input_application_opened(mt::fake_shared(session));
4468- input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface1));
4469- input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface2));
4470+ input_registrar->input_surface_opened(mt::fake_shared(surface1));
4471+ input_registrar->input_surface_opened(mt::fake_shared(surface2));
4472
4473 EXPECT_CALL(*event_filter, handles(_)).Times(3).WillRepeatedly(Return(false));
4474
4475@@ -357,17 +370,17 @@
4476 fake_event_hub->synthesize_builtin_keyboard_added();
4477 fake_event_hub->synthesize_device_scan_complete();
4478
4479- input_target_listener->focus_changed(mt::fake_shared(surface1));
4480+ input_targeter->focus_changed(mt::fake_shared(surface1));
4481 fake_event_hub->synthesize_event(mis::a_key_down_event()
4482 .of_scancode(KEY_1));
4483 wait1.wait_for_at_most_seconds(1);
4484
4485- input_target_listener->focus_changed(mt::fake_shared(surface2));
4486+ input_targeter->focus_changed(mt::fake_shared(surface2));
4487 fake_event_hub->synthesize_event(mis::a_key_down_event()
4488 .of_scancode(KEY_2));
4489 wait2.wait_for_at_most_seconds(1);
4490
4491- input_target_listener->focus_changed(mt::fake_shared(surface1));
4492+ input_targeter->focus_changed(mt::fake_shared(surface1));
4493 fake_event_hub->synthesize_event(mis::a_key_down_event()
4494 .of_scancode(KEY_3));
4495 wait3.wait_for_at_most_seconds(5);
4496
4497=== removed file 'tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp'
4498--- tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 2013-05-28 17:47:03 +0000
4499+++ tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 1970-01-01 00:00:00 +0000
4500@@ -1,118 +0,0 @@
4501-/*
4502- * Copyright © 2012 Canonical Ltd.
4503- *
4504- * This program is free software: you can redistribute it and/or modify
4505- * it under the terms of the GNU General Public License version 3 as
4506- * published by the Free Software Foundation.
4507- *
4508- * This program is distributed in the hope that it will be useful,
4509- * but WITHOUT ANY WARRANTY; without even the implied warranty of
4510- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4511- * GNU General Public License for more details.
4512- *
4513- * You should have received a copy of the GNU General Public License
4514- * along with this program. If not, see <http://www.gnu.org/licenses/>.
4515- *
4516- * Authored by: Robert Carr <robert.carr@canonical.com>
4517- * Daniel d'Andrada <daniel.dandrada@canonical.com>
4518- */
4519-#include "src/server/input/android/event_filter_dispatcher_policy.h"
4520-#include "src/server/input/android/rudimentary_input_reader_policy.h"
4521-#include "src/server/input/android/android_input_constants.h"
4522-
4523-#include "mir/input/event_filter.h"
4524-#include "mir/input/null_input_report.h"
4525-
4526-#include "mir_test/fake_shared.h"
4527-#include "mir_test/fake_event_hub.h"
4528-#include "mir_test_doubles/mock_event_filter.h"
4529-#include "mir_test/wait_condition.h"
4530-#include "mir_test/event_factory.h"
4531-#include "mir_test/event_matchers.h"
4532-
4533-#include <InputDispatcher.h>
4534-#include <InputReader.h>
4535-
4536-#include <gmock/gmock.h>
4537-#include <gtest/gtest.h>
4538-
4539-namespace mi = mir::input;
4540-namespace mia = mi::android;
4541-namespace mis = mir::input::synthesis;
4542-namespace mt = mir::test;
4543-namespace mtd = mir::test::doubles;
4544-
4545-namespace mir
4546-{
4547-
4548-class FakeEventHubSetup : public testing::Test
4549-{
4550- public:
4551- FakeEventHubSetup()
4552- {
4553- }
4554-
4555- ~FakeEventHubSetup()
4556- {
4557- }
4558-
4559- void SetUp()
4560- {
4561- event_hub = new mia::FakeEventHub();
4562- dispatcher_policy = new mia::EventFilterDispatcherPolicy(mt::fake_shared(event_filter), false);
4563- reader_policy = new mia::RudimentaryInputReaderPolicy();
4564- dispatcher = new droidinput::InputDispatcher(dispatcher_policy, std::make_shared<mi::NullInputReport>());
4565- reader = new droidinput::InputReader(event_hub, reader_policy, dispatcher);
4566- reader_thread = new droidinput::InputReaderThread(reader);
4567- dispatcher_thread = new droidinput::InputDispatcherThread(dispatcher);
4568-
4569- dispatcher->setInputDispatchMode(mia::DispatchEnabled, mia::DispatchUnfrozen);
4570- dispatcher->setInputFilterEnabled(true);
4571-
4572- dispatcher_thread->run("InputDispatcher", droidinput::PRIORITY_URGENT_DISPLAY);
4573- reader_thread->run("InputReader", droidinput::PRIORITY_URGENT_DISPLAY);
4574- }
4575-
4576- void TearDown()
4577- {
4578- dispatcher_thread->requestExit();
4579- dispatcher->setInputDispatchMode(mia::DispatchDisabled, mia::DispatchFrozen);
4580- dispatcher_thread->join();
4581-
4582- reader_thread->requestExit();
4583- event_hub->wake();
4584- reader_thread->join();
4585- }
4586-
4587- protected:
4588- mtd::MockEventFilter event_filter;
4589- droidinput::sp<mia::FakeEventHub> event_hub;
4590- droidinput::sp<droidinput::InputDispatcherPolicyInterface> dispatcher_policy;
4591- droidinput::sp<droidinput::InputReaderPolicyInterface> reader_policy;
4592- droidinput::sp<droidinput::InputDispatcher> dispatcher;
4593- droidinput::sp<droidinput::InputReader> reader;
4594- droidinput::sp<droidinput::InputReaderThread> reader_thread;
4595- droidinput::sp<droidinput::InputDispatcherThread> dispatcher_thread;
4596-};
4597-
4598-}
4599-
4600-using mir::FakeEventHubSetup;
4601-
4602-TEST_F(FakeEventHubSetup, fake_event_hub_dispatches_to_filter)
4603-{
4604- using namespace ::testing;
4605-
4606- mt::WaitCondition wait_condition;
4607-
4608- EXPECT_CALL(event_filter, handles(mt::KeyDownEvent())).Times(1)
4609- .WillOnce(mt::ReturnFalseAndWakeUp(&wait_condition));
4610-
4611- event_hub->synthesize_builtin_keyboard_added();
4612- event_hub->synthesize_device_scan_complete();
4613-
4614- event_hub->synthesize_event(mis::a_key_down_event()
4615- .of_scancode(KEY_ENTER));
4616-
4617- wait_condition.wait_for_at_most_seconds(1);
4618-}
4619
4620=== modified file 'tests/integration-tests/shell/test_session_manager.cpp'
4621--- tests/integration-tests/shell/test_session_manager.cpp 2013-05-21 17:16:43 +0000
4622+++ tests/integration-tests/shell/test_session_manager.cpp 2013-05-30 19:33:26 +0000
4623@@ -28,13 +28,13 @@
4624 #include "mir/compositor/buffer_swapper.h"
4625 #include "mir/shell/surface_creation_parameters.h"
4626
4627-#include <gmock/gmock.h>
4628-#include <gtest/gtest.h>
4629 #include "mir_test/gmock_fixes.h"
4630 #include "mir_test/fake_shared.h"
4631 #include "mir_test_doubles/mock_surface_factory.h"
4632 #include "mir_test_doubles/mock_focus_setter.h"
4633-#include "mir_test_doubles/stub_input_target_listener.h"
4634+
4635+#include <gmock/gmock.h>
4636+#include <gtest/gtest.h>
4637
4638 namespace mc = mir::compositor;
4639 namespace me = mir::events;
4640@@ -53,7 +53,6 @@
4641 msh::RegistrationOrderFocusSequence sequence(container);
4642 mtd::MockFocusSetter focus_setter;
4643 std::shared_ptr<mf::Session> new_session;
4644- mtd::StubInputTargetListener input_target_listener;
4645 msh::NullSessionListener session_listener;
4646
4647 msh::SessionManager session_manager(
4648@@ -61,7 +60,6 @@
4649 container,
4650 mt::fake_shared(sequence),
4651 mt::fake_shared(focus_setter),
4652- mt::fake_shared(input_target_listener),
4653 mt::fake_shared(session_listener));
4654
4655 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
4656@@ -98,7 +96,6 @@
4657 msh::RegistrationOrderFocusSequence sequence(container);
4658 mtd::MockFocusSetter focus_setter;
4659 std::shared_ptr<mf::Session> new_session;
4660- mtd::StubInputTargetListener input_target_listener;
4661 msh::NullSessionListener session_listener;
4662
4663 msh::SessionManager session_manager(
4664@@ -106,7 +103,6 @@
4665 container,
4666 mt::fake_shared(sequence),
4667 mt::fake_shared(focus_setter),
4668- mt::fake_shared(input_target_listener),
4669 mt::fake_shared(session_listener));
4670
4671 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
4672
4673=== modified file 'tests/mir_test_framework/testing_server_options.cpp'
4674--- tests/mir_test_framework/testing_server_options.cpp 2013-05-21 15:11:41 +0000
4675+++ tests/mir_test_framework/testing_server_options.cpp 2013-05-30 19:33:26 +0000
4676@@ -28,9 +28,7 @@
4677 #include "mir/compositor/graphic_buffer_allocator.h"
4678 #include "mir/input/input_channel.h"
4679 #include "mir/input/input_manager.h"
4680-#include "mir/input/null_input_target_listener.h"
4681-#include "src/server/input/android/android_input_manager.h"
4682-#include "src/server/input/android/android_dispatcher_controller.h"
4683+#include "mir/input/null_input_configuration.h"
4684
4685 #include "mir_test_doubles/stub_buffer.h"
4686 #include "mir_test_doubles/stub_surface_builder.h"
4687@@ -43,7 +41,7 @@
4688 namespace mc = mir::compositor;
4689 namespace mg = mir::graphics;
4690 namespace mi = mir::input;
4691-namespace mia = mir::input::android;
4692+namespace ms = mir::surfaces;
4693 namespace mf = mir::frontend;
4694 namespace mtf = mir_test_framework;
4695 namespace mtd = mir::test::doubles;
4696@@ -182,24 +180,14 @@
4697 ("tests-use-real-input", po::value<bool>(), "Use real input in tests. [bool:default=false]");
4698 }
4699
4700-
4701-std::shared_ptr<mi::InputManager> mtf::TestingServerConfiguration::the_input_manager()
4702+std::shared_ptr<mi::InputConfiguration> mtf::TestingServerConfiguration::the_input_configuration()
4703 {
4704 auto options = the_options();
4705+
4706 if (options->get("tests-use-real-input", false))
4707- return std::make_shared<mia::InputManager>(the_input_configuration());
4708- else
4709- return std::make_shared<StubInputManager>();
4710-}
4711-
4712-std::shared_ptr<msh::InputTargetListener> mtf::TestingServerConfiguration::the_input_target_listener()
4713-{
4714- auto options = the_options();
4715-
4716- if (options->get("tests-use-real-input", false))
4717- return std::make_shared<mia::DispatcherController>(the_input_configuration());
4718- else
4719- return std::make_shared<mi::NullInputTargetListener>();
4720+ return DefaultServerConfiguration::the_input_configuration();
4721+ else
4722+ return std::make_shared<mi::NullInputConfiguration>();
4723 }
4724
4725 std::shared_ptr<mg::Platform> mtf::TestingServerConfiguration::the_graphics_platform()
4726
4727=== modified file 'tests/unit-tests/input/android/CMakeLists.txt'
4728--- tests/unit-tests/input/android/CMakeLists.txt 2013-04-24 21:54:41 +0000
4729+++ tests/unit-tests/input/android/CMakeLists.txt 2013-05-30 19:33:26 +0000
4730@@ -7,7 +7,8 @@
4731 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_communication_package.cpp
4732 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_application_handle.cpp
4733 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_window_handle.cpp
4734- ${CMAKE_CURRENT_SOURCE_DIR}/test_android_dispatcher_controller.cpp
4735+ ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_targeter.cpp
4736+ ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_target_enumerator.cpp
4737 )
4738
4739 set(
4740
4741=== modified file 'tests/unit-tests/input/android/test_android_input_application_handle.cpp'
4742--- tests/unit-tests/input/android/test_android_input_application_handle.cpp 2013-04-24 05:22:20 +0000
4743+++ tests/unit-tests/input/android/test_android_input_application_handle.cpp 2013-05-30 19:33:26 +0000
4744@@ -18,7 +18,7 @@
4745
4746 #include "src/server/input/android/android_input_application_handle.h"
4747
4748-#include "mir/input/session_target.h"
4749+#include "mir/input/surface_target.h"
4750
4751 #include <gtest/gtest.h>
4752 #include <gmock/gmock.h>
4753@@ -27,43 +27,47 @@
4754
4755 namespace mi = mir::input;
4756 namespace mia = mi::android;
4757+namespace geom = mir::geometry;
4758
4759 namespace
4760 {
4761-struct MockSessionHandle : public mi::SessionTarget
4762+struct MockSurfaceHandle : public mi::SurfaceTarget
4763 {
4764- MOCK_CONST_METHOD0(name, std::string());
4765+ MOCK_CONST_METHOD0(server_input_fd, int());
4766+ MOCK_CONST_METHOD0(top_left, geom::Point());
4767+ MOCK_CONST_METHOD0(size, geom::Size());
4768+ MOCK_CONST_METHOD0(name, std::string const&());
4769 };
4770 }
4771
4772
4773-TEST(AndroidInputApplicationHandle, takes_name_from_session_and_specifies_max_timeout)
4774+TEST(AndroidInputApplicationHandle, takes_name_from_surface_and_specifies_max_timeout)
4775 {
4776 using namespace ::testing;
4777- std::string const testing_session_name = "Cats";
4778- auto session = std::make_shared<MockSessionHandle>();
4779+ std::string testing_surface_name = "Cats";
4780+ auto surface = std::make_shared<MockSurfaceHandle>();
4781
4782- EXPECT_CALL(*session, name()).Times(AtLeast(1))
4783- .WillRepeatedly(Return(testing_session_name));
4784- mia::InputApplicationHandle application_handle(session);
4785+ EXPECT_CALL(*surface, name()).Times(AtLeast(1))
4786+ .WillRepeatedly(ReturnRef(testing_surface_name));
4787+ mia::InputApplicationHandle application_handle(surface);
4788 EXPECT_TRUE(application_handle.updateInfo());
4789 auto info = application_handle.getInfo();
4790 EXPECT_EQ(INT_MAX, info->dispatchingTimeout);
4791- EXPECT_EQ(droidinput::String8(testing_session_name.c_str()), info->name);
4792+ EXPECT_EQ(droidinput::String8(testing_surface_name.c_str()), info->name);
4793 }
4794
4795-TEST(AndroidInputApplicationHandle, does_not_own_session)
4796+TEST(AndroidInputApplicationHandle, does_not_own_surface)
4797 {
4798 using namespace ::testing;
4799- std::string const testing_session_name = "Let it Grow";
4800-
4801- auto session = std::make_shared<MockSessionHandle>();
4802- EXPECT_CALL(*session, name()).Times(AtLeast(1))
4803- .WillRepeatedly(Return(testing_session_name));
4804-
4805- mia::InputApplicationHandle application_handle(session);
4806+ std::string const testing_surface_name = "Let it Grow";
4807+
4808+ auto surface = std::make_shared<MockSurfaceHandle>();
4809+ EXPECT_CALL(*surface, name()).Times(AtLeast(1))
4810+ .WillRepeatedly(ReturnRef(testing_surface_name));
4811+
4812+ mia::InputApplicationHandle application_handle(surface);
4813 EXPECT_TRUE(application_handle.updateInfo());
4814- session.reset();
4815+ surface.reset();
4816 EXPECT_FALSE(application_handle.updateInfo());
4817
4818 }
4819
4820=== modified file 'tests/unit-tests/input/android/test_android_input_manager.cpp'
4821--- tests/unit-tests/input/android/test_android_input_manager.cpp 2013-05-13 09:35:44 +0000
4822+++ tests/unit-tests/input/android/test_android_input_manager.cpp 2013-05-30 19:33:26 +0000
4823@@ -21,15 +21,11 @@
4824 #include "src/server/input/android/android_input_constants.h"
4825
4826 #include "mir/input/input_channel.h"
4827-#include "mir/input/session_target.h"
4828 #include "mir/input/surface_target.h"
4829-#include "mir/input/android/android_input_configuration.h"
4830
4831 #include "mir_test/fake_shared.h"
4832 #include "mir_test_doubles/mock_viewable_area.h"
4833 #include "mir_test_doubles/mock_input_dispatcher.h"
4834-#include "mir_test_doubles/mock_input_configuration.h"
4835-#include "mir_test_doubles/stub_session_target.h"
4836 #include "mir_test_doubles/stub_surface_target.h"
4837
4838 #include <EventHub.h>
4839@@ -116,15 +112,9 @@
4840 dispatcher = new mtd::MockInputDispatcher();
4841 dispatcher_thread = std::make_shared<MockInputThread>();
4842 reader_thread = std::make_shared<MockInputThread>();
4843-
4844- ON_CALL(config, the_event_hub()).WillByDefault(Return(event_hub));
4845- ON_CALL(config, the_dispatcher()).WillByDefault(Return(dispatcher));
4846- ON_CALL(config, the_reader_thread()).WillByDefault(Return(reader_thread));
4847- ON_CALL(config, the_dispatcher_thread()).WillByDefault(Return(dispatcher_thread));
4848 }
4849 mtd::MockViewableArea view_area;
4850
4851- testing::NiceMock<mtd::MockInputConfiguration> config;
4852 droidinput::sp<MockEventHub> event_hub;
4853 droidinput::sp<mtd::MockInputDispatcher> dispatcher;
4854 std::shared_ptr<MockInputThread> dispatcher_thread;
4855@@ -133,19 +123,6 @@
4856
4857 }
4858
4859-TEST_F(AndroidInputManagerSetup, takes_input_setup_from_configuration)
4860-{
4861- using namespace ::testing;
4862-
4863- EXPECT_CALL(config, the_event_hub()).Times(1);
4864- EXPECT_CALL(config, the_dispatcher()).Times(1);
4865- EXPECT_CALL(config, the_reader_thread()).Times(1);
4866- EXPECT_CALL(config, the_dispatcher_thread()).Times(1);
4867-
4868- mia::InputManager manager(mt::fake_shared(config));
4869-
4870-}
4871-
4872 TEST_F(AndroidInputManagerSetup, start_and_stop)
4873 {
4874 using namespace ::testing;
4875@@ -180,7 +157,7 @@
4876 EXPECT_CALL(*reader_thread, join());
4877 }
4878
4879- mia::InputManager manager(mt::fake_shared(config));
4880+ mia::InputManager manager(event_hub, dispatcher, reader_thread, dispatcher_thread);
4881
4882 manager.start();
4883 manager.stop();
4884@@ -188,7 +165,7 @@
4885
4886 TEST_F(AndroidInputManagerSetup, manager_returns_input_channel_with_fds)
4887 {
4888- mia::InputManager manager(mt::fake_shared(config));
4889+ mia::InputManager manager(event_hub, dispatcher, reader_thread, dispatcher_thread);
4890
4891 auto package = manager.make_input_channel();
4892 EXPECT_GT(package->client_fd(), 0);
4893
4894=== renamed file 'tests/unit-tests/input/android/test_android_dispatcher_controller.cpp' => 'tests/unit-tests/input/android/test_android_input_registrar.cpp'
4895--- tests/unit-tests/input/android/test_android_dispatcher_controller.cpp 2013-05-02 00:11:18 +0000
4896+++ tests/unit-tests/input/android/test_android_input_registrar.cpp 2013-05-30 19:33:26 +0000
4897@@ -16,11 +16,10 @@
4898 * Authored by: Robert Carr <robert.carr@canonical.com>
4899 */
4900
4901-#include "src/server/input/android/android_dispatcher_controller.h"
4902+#include "src/server/input/android/android_input_registrar.h"
4903
4904 #include "mir_test_doubles/mock_input_configuration.h"
4905 #include "mir_test_doubles/mock_input_dispatcher.h"
4906-#include "mir_test_doubles/stub_session_target.h"
4907 #include "mir_test_doubles/stub_surface_target.h"
4908
4909 #include "mir_test/fake_shared.h"
4910@@ -44,7 +43,7 @@
4911 // TODO: It would be nice if it were possible to mock the interface between
4912 // droidinput::InputChannel and droidinput::InputDispatcher rather than use
4913 // valid fds to allow non-throwing construction of a real input channel.
4914-struct AndroidDispatcherControllerFdSetup : public testing::Test
4915+struct AndroidInputRegistrarFdSetup : public testing::Test
4916 {
4917 void SetUp() override
4918 {
4919@@ -61,200 +60,57 @@
4920 mtd::MockInputConfiguration config;
4921 };
4922
4923-static bool
4924-application_handle_matches_session(droidinput::sp<droidinput::InputApplicationHandle> const& handle,
4925- std::shared_ptr<mi::SessionTarget> const& session)
4926-{
4927- if (handle->getName() != droidinput::String8(session->name().c_str()))
4928- return false;
4929- return true;
4930-}
4931-
4932-static bool
4933-window_handle_matches_session_and_surface(droidinput::sp<droidinput::InputWindowHandle> const& handle,
4934- std::shared_ptr<mi::SessionTarget> const& session,
4935- std::shared_ptr<mi::SurfaceTarget> const& surface)
4936-{
4937- if (!application_handle_matches_session(handle->inputApplicationHandle, session))
4938- return false;
4939- if (handle->getInputChannel()->getFd() != surface->server_input_fd())
4940+MATCHER_P(WindowHandleFor, surface, "")
4941+{
4942+ if (arg->getInputChannel()->getFd() != surface->server_input_fd())
4943 return false;
4944 return true;
4945 }
4946
4947-MATCHER_P2(WindowHandleFor, session, surface, "")
4948-{
4949- return window_handle_matches_session_and_surface(arg, session, surface);
4950-}
4951-
4952-MATCHER_P(ApplicationHandleFor, session, "")
4953-{
4954- return application_handle_matches_session(arg, session);
4955-}
4956-
4957-MATCHER_P2(VectorContainingWindowHandleFor, session, surface, "")
4958-{
4959- auto i = arg.size();
4960- for (i = 0; i < arg.size(); i++)
4961- {
4962- if (window_handle_matches_session_and_surface(arg[i], session, surface))
4963- return true;
4964- }
4965- return false;
4966-}
4967-
4968-MATCHER(EmptyVector, "")
4969-{
4970- return arg.size() == 0;
4971-}
4972-
4973-}
4974-
4975-TEST_F(AndroidDispatcherControllerFdSetup, input_application_opened_behavior)
4976-{
4977- using namespace ::testing;
4978-
4979- EXPECT_CALL(config, the_dispatcher()).Times(1)
4980- .WillOnce(Return(dispatcher));
4981- mia::DispatcherController controller(mt::fake_shared(config));
4982-
4983- auto session = std::make_shared<mtd::StubSessionTarget>();
4984- controller.input_application_opened(session);
4985- EXPECT_THROW({
4986- // An application can not be opened twice!
4987- controller.input_application_opened(session);
4988- }, std::logic_error);
4989-}
4990-
4991-TEST_F(AndroidDispatcherControllerFdSetup, input_application_closed_behavior)
4992-{
4993- using namespace ::testing;
4994-
4995- EXPECT_CALL(config, the_dispatcher()).Times(1)
4996- .WillOnce(Return(dispatcher));
4997- mia::DispatcherController controller(mt::fake_shared(config));
4998-
4999- auto session = std::make_shared<mtd::StubSessionTarget>();
5000- EXPECT_THROW({
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches