Merge lp:~robertcarr/mir/receive-input-in-client into lp:~mir-team/mir/trunk
- receive-input-in-client
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Thomas Voß | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 562 | ||||
Proposed branch: | lp:~robertcarr/mir/receive-input-in-client | ||||
Merge into: | lp:~mir-team/mir/trunk | ||||
Diff against target: |
3169 lines (+1583/-233) 69 files modified
3rd_party/CMakeLists.txt (+2/-6) 3rd_party/android-deps/std/SortedVector.h (+1/-1) 3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h (+2/-0) 3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp (+5/-0) CMakeLists.txt (+0/-7) cross-compile-chroot.sh (+0/-1) debian/rules (+0/-1) doc/building_source_for_android.md (+2/-2) examples/demo_client.c (+1/-1) examples/demo_client_accelerated.cpp (+1/-1) examples/demo_client_unaccelerated.c (+1/-1) examples/eglapp.c (+14/-1) examples/render_surfaces.cpp (+2/-16) include/client/mir_toolkit/mir_client_library.h (+3/-1) include/server/mir/input/null_input_manager.h (+56/-0) include/shared/mir/input/android/android_input_lexicon.h (+7/-0) include/shared/mir_toolkit/c_types.h (+21/-0) include/shared/mir_toolkit/input/event.h (+2/-2) include/test/mir_test/wait_condition.h (+5/-3) src/client/CMakeLists.txt (+10/-3) src/client/input/CMakeLists.txt (+12/-0) src/client/input/android_input_platform.cpp (+44/-0) src/client/input/android_input_platform.h (+52/-0) src/client/input/android_input_receiver.cpp (+91/-0) src/client/input/android_input_receiver.h (+84/-0) src/client/input/android_input_receiver_thread.cpp (+68/-0) src/client/input/android_input_receiver_thread.h (+71/-0) src/client/input/input_platform.h (+55/-0) src/client/input/input_receiver_thread.h (+48/-0) src/client/mir_client_library.cpp (+10/-6) src/client/mir_client_surface.h (+1/-0) src/client/mir_connection.cpp (+8/-2) src/client/mir_connection.h (+7/-0) src/client/mir_surface.cpp (+19/-1) src/client/mir_surface.h (+13/-0) src/server/CMakeLists.txt (+1/-0) src/server/default_server_configuration.cpp (+7/-2) src/server/frontend/protobuf_message_processor.cpp (+4/-2) src/server/input/CMakeLists.txt (+0/-7) src/server/input/android/CMakeLists.txt (+1/-1) src/server/input/android/android_input_application_handle.cpp (+6/-1) src/server/input/android/android_input_application_handle.h (+1/-1) src/server/input/android/event_filter_dispatcher_policy.cpp (+3/-2) src/server/input/android/transport/CMakeLists.txt (+31/-0) src/server/input/android/transport/android_input_lexicon.cpp (+7/-7) src/server/input/dummy_input_manager.cpp (+0/-42) tests/acceptance-tests/CMakeLists.txt (+4/-0) tests/acceptance-tests/test_client_input.cpp (+268/-0) tests/acceptance-tests/test_client_library.cpp (+7/-7) tests/acceptance-tests/test_focus_management_api.cpp (+1/-1) tests/acceptance-tests/test_focus_selection.cpp (+1/-1) tests/acceptance-tests/test_surfaceloop.cpp (+5/-5) tests/integration-tests/CMakeLists.txt (+0/-2) tests/integration-tests/client/test_client_render.cpp (+8/-8) tests/integration-tests/input/android/test_android_cursor_listener.cpp (+2/-3) tests/integration-tests/input/android/test_android_input_manager.cpp (+8/-9) tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp (+2/-3) tests/integration-tests/test_error_reporting.cpp (+1/-1) tests/integration-tests/test_surfaceloop.cpp (+4/-4) tests/mir_test_doubles/CMakeLists.txt (+0/-2) tests/unit-tests/CMakeLists.txt (+0/-3) tests/unit-tests/client/CMakeLists.txt (+4/-0) tests/unit-tests/client/input/CMakeLists.txt (+9/-0) tests/unit-tests/client/input/test_android_input_receiver.cpp (+198/-0) tests/unit-tests/client/input/test_android_input_receiver_thread.cpp (+152/-0) tests/unit-tests/client/test_client_mir_surface.cpp (+106/-51) tests/unit-tests/input/android/test_android_input_application_handle.cpp (+18/-6) tests/unit-tests/input/android/test_android_input_lexicon.cpp (+5/-5) tests/unit-tests/input/android/test_android_input_window_handle.cpp (+1/-1) |
||||
To merge this branch: | bzr merge lp:~robertcarr/mir/receive-input-in-client | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Alan Griffiths | Approve | ||
Chris Halse Rogers | Approve | ||
Review via email: mp+155368@code.launchpad.net |
Commit message
Enable end-to-end keyboard input and test through tests/acceptanc
Description of the change
This branch contains the client side of input and the finishing touches required to make keyboard input delivery work end to end!
The driving acceptance test is shown in tests/acceptanc
See test_client_
The input machinery on the client side is mclia::
Some changes to protobuf_
Currently this is failing to work with MIR_INPUT_
On the other hand with MIR_INPUT_
Some notes from my own look at the diff
* Should the event handler type take MirSurface as the first argument? So far this hasn't been useful. If so, perhaps the EventDelegate should be passed to the Connection, it could be for other kinds of callbacks (such as?...application focus maybe?) as well. ubuntu_platform_api uses no Surface as the first argument and delegate attached to surface (or rather two argument callback, context). Maybe we should just work this way? Seems a shame to not use a delegate struct though as we will just be continually adding arguments (focus_changed_cb, proximity_cb (strawman ;)) etc...)
* The continual writing of std::function<
Robert Carr (robertcarr) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:582
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:585
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:586
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : | # |
Trunk merged. There were some tricky bits around test_client_
and so the test appeared to pass when really it should have failed.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:587
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Chris Halse Rogers (raof) wrote : | # |
In general: at least a little bit of Doxygen comments for the classes you add, please! ☺
-------
716 + droidinput:
717 + if((status = input_consumer-
718 + default_frame_time, &event_sequence_id, &android_event)) != droidinput:
Status is set but never used.
-------
807 + int get_fd() const;
I think we'd generally expect this to be called just ‘fd()’?
-------
822 + static const bool consume_batches = true;
823 + static const bool do_not_
...
825 + static const bool handle_event = true;
826 + static const bool do_not_handle_event = false;
As far as I'm aware we've not been using this pattern elsewhere in the code? I'm not particularly against it, though.
-------
739 + auto status = ::poll(&pfd, 1, timeout.count());
740 +
741 + if (status > 0)
742 + return true;
743 + if (status == 0)
744 + return false;
745 +
746 + // TODO: What to do in case of error? ~racarr
747 + return false;
748 +}
This should probably try polling(!) again while status == EINTR.
Other errors should probably be runtime exceptions; none of the other errors poll can return (EFAULT, EINVAL, ENOMEM) are going to go away without explicit action.
I'm not comfortable letting this in while we're polling every 10msec for input.
Robert Carr (robertcarr) wrote : | # |
>>> In general: at least a little bit of Doxygen comments for the classes you add, please! ☺
I tried to add some helpful comments!
>> 716 + droidinput:
>> 717 + if((status = input_consumer-
>> 718 + default_frame_time, &event_sequence_id, &android_event)) != droidinput:
>> Status is set but never used.
Fixed
>> 807 + int get_fd() const;
Fixed
-------
>> 822 + static const bool consume_batches = true;
>> 823 + static const bool do_not_
...
>> 825 + static const bool handle_event = true;
>> 826 + static const bool do_not_handle_event = false;
>> As far as I'm aware we've not been using this pattern elsewhere in the code? I'm not particularly against >> it, though.
These come from a long series of reviews on an original version of AndroidInputRec
-------
>> I'm not comfortable letting this in while we're polling every 10msec for input.
The custom poll implementation is replaced with a droidinput::Looper, this way the poll is indefinite, but may still be woken by a wake pipe from another thread.
Robert Carr (robertcarr) wrote : | # |
l725 is a mystery to me. It's easy to observe: Moving it to the constructor causes the acceptance test to fail intermittently.
Robert Carr (robertcarr) wrote : | # |
I'd like to add an exception here:
+ else if (result == ALOOPER_POLL_ERROR) // TODO: Exception?
It's difficult though without a mockable looper to test this exception so I would suggest we target it for a follow-up mp
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:590
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:592
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:595
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:596
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
Why is "MirEventDelegate const *event_handler" a separate parameter and not a member of MirSurfaceParam
~~~~
563 + virtual ~TestingClientC
Is this necessary? And shouldn't it be "virtual ~TestingClientC
~~~~
550 +#include <gmock/gmock.h>
There are worse things wrong with this file:
o WaitCondition doesn't belong in namespace mir
o anonymous namespaces make things unique to each translation units, and should rarely appear in headers.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:599
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:601
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:603
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:604
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:605
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
> >> 822 + static const bool consume_batches = true;
> >> 823 + static const bool do_not_
> ...
> >> 825 + static const bool handle_event = true;
> >> 826 + static const bool do_not_handle_event = false;
>
> >> As far as I'm aware we've not been using this pattern elsewhere in the
> code? I'm not particularly against >> it, though.
>
> These come from a long series of reviews on an original version of
> AndroidInputRec
> do think they make the implementation read in a rather literate style.
Where are we using it here? I find no use of "do_not_
It is better to use "enum class BatchMode { do_not_
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:609
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : | # |
* General cleanup and fix valgrind complaints r606-610
* Android input application handle should take a weak reference to prevent circular ownership. (r608)
* Remove strange constants
* Cleanup wait_condition.h
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:610
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:612
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:615
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:616
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
321 InputMessage msg;
322 + memset(&msg, 0, sizeof(
...
330 InputMessage msg;
331 + memset(&msg, 0, sizeof(
...
339 InputMessage msg;
340 + memset(&msg, 0, sizeof(
Wouldn't a default constructor be less repetitive?
~~~~
Why is "MirEventDelegate const *event_handler" a separate parameter and not a member of MirSurfaceParam
~~~~
"Should the event handler type take MirSurface as the first argument? ... ubuntu_platform_api uses no Surface as the first argument and delegate attached to surface (or rather two argument callback, context). Maybe we should just work this way?"
Robert Carr (robertcarr) wrote : | # |
>> 321 InputMessage msg;
>> 322 + memset(&msg, 0, sizeof(
>> ...
>> 330 InputMessage msg;
>> 331 + memset(&msg, 0, sizeof(
>> ...
>> 339 InputMessage msg;
>> 340 + memset(&msg, 0, sizeof(
Yes it would says r618.
>> Why is "MirEventDelegate const *event_handler" a separate parameter and not a member of
>> MirSurfaceParam
I think it's a very different kind of parameter (not sent over the wire to the server, not used for construction, not serializable). Maybe the API user doesn't care?
>> "Should the event handler type take MirSurface as the first argument? ... ubuntu_platform_api uses no
>> Surface as the first argument and delegate attached to surface (or rather two argument callback, context). >> Maybe we should just work this way?"
This was just kind of a thought I threw out. I like the current signature (surface, ev, ctx) and it is in keeping with C style used in GLib, etc...
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:618
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
Spurious whitespace:
1302 -
1303 +
Alan Griffiths (alan-griffiths) wrote : | # |
Probably OK once the conflict is fixed
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:619
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:620
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:621
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
1236 -
1237 +
Spurious whitespace
Alan Griffiths (alan-griffiths) wrote : | # |
2667 - auto surface = std::make_
2668 - *client_
2669 - logger,
2670 - mock_buffer_
2671 - params,
2672 - &empty_callback,
2673 - nullptr);
2674 + auto surface = std::make_
Using "(void*) NULL" in place of "nullptr" isn't an improvement.
Alan Griffiths (alan-griffiths) wrote : | # |
333 +
Spurious whitespace
There's also some NULL usage.
But I'll abstain as there's nothing obvious to block on and I'm at EOD.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:623
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : | # |
Many whitespace and style fixes
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:639
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Chris Halse Rogers (raof) wrote : | # |
So, we can probably land this, and do some followup cleaning:
155 + surface = mir_surface_
Might as well use nullptr here (and change the surrounding NULL checks).
src/client/
src/client/
src/client/
src/client/
…and basically all the added files, it seems.
A bunch of cases of ~Foo() {}, which I think would more idiomatically be ~Foo() = default;
1356 + ("enable-input,i", po::value<bool>(), "Enable input. [bool:default=
1357 (log_display, po::value<bool>(), "Log the Display report. [bool:default=
1358 (log_app_mediator, po::value<bool>(), "Log the ApplicationMediator report. [bool:default=
1359 (log_msg_processor, po::value<bool>(), "log the MessageProcessor report")
1360 @@ -316,9 +318,12 @@
1361 mir::DefaultSer
1362 {
1363 return input_manager(
1364 - [&, this]()
1365 + [&, this]() -> std::shared_
1366 {
1367 - return mi::create_
1368 + if (the_options(
1369 + return mi::create_
1370 + else
1371 + return std::make_
Is this the right way around? It looks like input is turned off if ‘enable-input’ is true?
2641 +// thread->join();
Looks like you've got some temporary testing code still hanging around?
2883 - auto surface = std::make_
2884 - *client_
2885 - logger,
2886 - mock_buffer_
2887 - params,
2888 - &empty_callback,
2889 - nullptr);
2890 + auto surface = std::make_
(and further examples in that file)
I think we prefer the former formatting, with shorter lines?
Alan Griffiths (alan-griffiths) wrote : | # |
> 1368 + if (the_options(
> 1369 + return mi::create_
> the_display());
> 1370 + else
> 1371 + return std::make_
>
> Is this the right way around? It looks like input is turned off if ‘enable-
> input’ is true?
It is the right way "false" is the default value for get. Maybe we should add a helper function so that we can write "the_options(
Alan Griffiths (alan-griffiths) wrote : | # |
>So, we can probably land this, and do some followup cleaning:
+1
...
> src/client/
> src/client/
> src/client/
> LGPLv3+
> src/client/
> …and basically all the added files, it seems.
>
> A bunch of cases of ~Foo() {}, which I think would more idiomatically be
> ~Foo() = default;
We can probably fix this when we clean up a whole bunch of potentially throwing destructors.
> 2641 +// thread->join();
>
> Looks like you've got some temporary testing code still hanging around?
>
> 2883 - auto surface = std::make_
> 2884 -
> *client_
> 2885 - logger,
> 2886 - mock_buffer_
> 2887 - params,
> 2888 - &empty_callback,
> 2889 - nullptr);
> 2890 + auto surface = std::make_
> *client_
> nullptr, &empty_callback, nullptr);
> (and further examples in that file)
> I think we prefer the former formatting, with shorter lines?
I think we should prefer a third style - breaking before the first parameter when necessary. (The original is fragile when renaming anything that appears before that point - and we do global renames often enough for it to matter.)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
Unapproved changes made after approval.
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file '3rd_party/CMakeLists.txt' |
2 | --- 3rd_party/CMakeLists.txt 2013-03-21 03:32:59 +0000 |
3 | +++ 3rd_party/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
4 | @@ -28,10 +28,8 @@ |
5 | add_subdirectory(android-fbtype) |
6 | endif() |
7 | |
8 | -if (NOT MIR_DISABLE_INPUT) |
9 | - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/android-deps) |
10 | - add_subdirectory(android-input) |
11 | -endif() |
12 | +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/android-deps) |
13 | +add_subdirectory(android-input) |
14 | |
15 | set(MIR_ANDROID_INCLUDE_DIRECTORIES ${MIR_ANDROID_INCLUDE_DIRECTORIES} PARENT_SCOPE) |
16 | set( |
17 | @@ -39,9 +37,7 @@ |
18 | ${MIR_ANDROID_INPUT_COMPILE_FLAGS} |
19 | PARENT_SCOPE) |
20 | |
21 | -if (NOT MIR_DISABLE_INPUT) |
22 | target_link_libraries( |
23 | 3rd_party |
24 | |
25 | android-input) |
26 | -endif() |
27 | |
28 | === modified file '3rd_party/android-deps/std/SortedVector.h' |
29 | --- 3rd_party/android-deps/std/SortedVector.h 2013-03-13 04:54:15 +0000 |
30 | +++ 3rd_party/android-deps/std/SortedVector.h 2013-04-03 18:49:21 +0000 |
31 | @@ -133,7 +133,7 @@ |
32 | ssize_t remove(const ValueType& item) |
33 | { |
34 | auto remove_pos = lower_bound(begin(), end(), item); |
35 | - if (*remove_pos == item) |
36 | + if (remove_pos != end() && *remove_pos == item) |
37 | { |
38 | auto removed_at = erase(remove_pos); |
39 | return distance(begin(), removed_at); |
40 | |
41 | === modified file '3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h' |
42 | --- 3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h 2013-03-13 04:54:15 +0000 |
43 | +++ 3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h 2013-04-03 18:49:21 +0000 |
44 | @@ -43,6 +43,8 @@ |
45 | * Intermediate representation used to send input events and related signals. |
46 | */ |
47 | struct InputMessage { |
48 | + InputMessage(); |
49 | + |
50 | enum { |
51 | TYPE_KEY = 1, |
52 | TYPE_MOTION = 2, |
53 | |
54 | === modified file '3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp' |
55 | --- 3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp 2013-02-11 11:51:22 +0000 |
56 | +++ 3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp 2013-04-03 18:49:21 +0000 |
57 | @@ -63,6 +63,11 @@ |
58 | |
59 | // --- InputMessage --- |
60 | |
61 | +InputMessage::InputMessage() |
62 | +{ |
63 | + memset(this, 0, sizeof(InputMessage)); |
64 | +} |
65 | + |
66 | bool InputMessage::isValid(size_t actualSize) const { |
67 | if (size() == actualSize) { |
68 | switch (header.type) { |
69 | |
70 | === modified file 'CMakeLists.txt' |
71 | --- CMakeLists.txt 2013-03-28 14:20:06 +0000 |
72 | +++ CMakeLists.txt 2013-04-03 18:49:21 +0000 |
73 | @@ -103,13 +103,6 @@ |
74 | "graphics backend to build (options are 'gbm' or 'android')" |
75 | ) |
76 | |
77 | -set (MIR_DISABLE_INPUT |
78 | - false |
79 | - CACHE |
80 | - BOOL |
81 | - "Don't build the input subsystem" |
82 | -) |
83 | - |
84 | set (MIR_INPUT_USE_ANDROID_TYPES |
85 | false |
86 | CACHE |
87 | |
88 | === modified file 'cross-compile-chroot.sh' |
89 | --- cross-compile-chroot.sh 2013-03-26 15:55:51 +0000 |
90 | +++ cross-compile-chroot.sh 2013-04-03 18:49:21 +0000 |
91 | @@ -26,7 +26,6 @@ |
92 | -DBoost_COMPILER=-gcc \ |
93 | -DMIR_ENABLE_DEATH_TESTS=NO \ |
94 | -DMIR_PLATFORM=android \ |
95 | - -DMIR_DISABLE_INPUT=true \ |
96 | .. |
97 | |
98 | cmake --build . |
99 | |
100 | === modified file 'debian/rules' |
101 | --- debian/rules 2013-03-13 04:54:15 +0000 |
102 | +++ debian/rules 2013-04-03 18:49:21 +0000 |
103 | @@ -15,7 +15,6 @@ |
104 | |
105 | COMMON_CONFIGURE_OPTIONS = \ |
106 | -DMIR_DISABLE_EPOLL_REACTOR=YES \ |
107 | - -DMIR_DISABLE_INPUT=YES \ |
108 | -DBUILD_DOXYGEN=YES |
109 | |
110 | # We need to rely on the select-based reactor to fix the ppa builds. |
111 | |
112 | === modified file 'doc/building_source_for_android.md' |
113 | --- doc/building_source_for_android.md 2013-03-26 16:30:53 +0000 |
114 | +++ doc/building_source_for_android.md 2013-04-03 18:49:21 +0000 |
115 | @@ -42,7 +42,7 @@ |
116 | |
117 | $ bzr branch lp:mir |
118 | $ mkdir mir/build; cd mir/build |
119 | - $ cmake -DBoost_COMPILER=-gcc -DMIR_ENABLE_DEATH_TESTS=NO -DMIR_PLATFORM=android -DMIR_DISABLE_INPUT=yes .. |
120 | + $ cmake -DBoost_COMPILER=-gcc -DMIR_ENABLE_DEATH_TESTS=NO -DMIR_PLATFORM=android .. |
121 | |
122 | Cross Compile |
123 | ------------- |
124 | @@ -63,7 +63,7 @@ |
125 | |
126 | $ bzr branch lp:mir |
127 | $ mkdir mir/build; cd mir/build |
128 | - $ MIR_NDK_PATH=/path/to/depenendcies/chroot cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/LinuxCrossCompile.cmake -DBoost_COMPILER=-gcc -DMIR_ENABLE_DEATH_TESTS=NO -DMIR_PLATFORM=android -DMIR_DISABLE_INPUT=yes .. |
129 | + $ MIR_NDK_PATH=/path/to/depenendcies/chroot cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/LinuxCrossCompile.cmake -DBoost_COMPILER=-gcc -DMIR_ENABLE_DEATH_TESTS=NO -DMIR_PLATFORM=android .. |
130 | $ make |
131 | |
132 | N.B. The `cross-compile-android.sh` script in mir's top level directory |
133 | |
134 | === modified file 'examples/demo_client.c' |
135 | --- examples/demo_client.c 2013-03-22 10:34:16 +0000 |
136 | +++ examples/demo_client.c 2013-04-03 18:49:21 +0000 |
137 | @@ -129,7 +129,7 @@ |
138 | /// \snippet demo_client.c surface_create_tag |
139 | ///\internal [surface_create_tag] |
140 | // ...we create a surface using that format and wait for callback to complete. |
141 | - mir_wait_for(mir_surface_create(mcd.connection, &request_params, surface_create_callback, &mcd)); |
142 | + mir_wait_for(mir_surface_create(mcd.connection, &request_params, NULL, surface_create_callback, &mcd)); |
143 | puts("Surface created"); |
144 | ///\internal [surface_create_tag] |
145 | |
146 | |
147 | === modified file 'examples/demo_client_accelerated.cpp' |
148 | --- examples/demo_client_accelerated.cpp 2013-03-22 10:34:16 +0000 |
149 | +++ examples/demo_client_accelerated.cpp 2013-04-03 18:49:21 +0000 |
150 | @@ -72,7 +72,7 @@ |
151 | MirSurfaceParameters const request_params = |
152 | {__PRETTY_FUNCTION__, 640, 480, pixel_format, mir_buffer_usage_hardware}; |
153 | |
154 | - surface = mir_surface_create_sync(connection, &request_params); |
155 | + surface = mir_surface_create_sync(connection, &request_params, NULL); |
156 | assert(surface != NULL); |
157 | assert(mir_surface_is_valid(surface)); |
158 | assert(strcmp(mir_surface_get_error_message(surface), "") == 0); |
159 | |
160 | === modified file 'examples/demo_client_unaccelerated.c' |
161 | --- examples/demo_client_unaccelerated.c 2013-03-29 16:51:35 +0000 |
162 | +++ examples/demo_client_unaccelerated.c 2013-04-03 18:49:21 +0000 |
163 | @@ -132,7 +132,7 @@ |
164 | MirSurfaceParameters const request_params = |
165 | {__PRETTY_FUNCTION__, 640, 480, pixel_format, mir_buffer_usage_software}; |
166 | |
167 | - surface = mir_surface_create_sync(connection, &request_params); |
168 | + surface = mir_surface_create_sync(connection, &request_params, NULL); |
169 | assert(surface != NULL); |
170 | assert(mir_surface_is_valid(surface)); |
171 | assert(strcmp(mir_surface_get_error_message(surface), "") == 0); |
172 | |
173 | === modified file 'examples/eglapp.c' |
174 | --- examples/eglapp.c 2013-03-20 05:03:03 +0000 |
175 | +++ examples/eglapp.c 2013-04-03 18:49:21 +0000 |
176 | @@ -85,6 +85,14 @@ |
177 | } |
178 | } |
179 | |
180 | +static void mir_eglapp_handle_input(MirSurface* surface, MirEvent* ev, void* context) |
181 | +{ |
182 | + (void) surface; |
183 | + (void) context; |
184 | + if (ev->details.key.key_code == 45) /* Q */ |
185 | + running = 0; |
186 | +} |
187 | + |
188 | mir_eglapp_bool mir_eglapp_init(int *width, int *height) |
189 | { |
190 | EGLint attribs[] = |
191 | @@ -106,6 +114,11 @@ |
192 | mir_pixel_format_xbgr_8888, |
193 | mir_buffer_usage_hardware |
194 | }; |
195 | + MirEventDelegate delegate = |
196 | + { |
197 | + mir_eglapp_handle_input, |
198 | + NULL |
199 | + }; |
200 | MirDisplayInfo dinfo; |
201 | MirSurface *surface; |
202 | EGLConfig eglconfig; |
203 | @@ -127,7 +140,7 @@ |
204 | surfaceparm.pixel_format = dinfo.supported_pixel_format[0]; |
205 | printf("Using pixel format #%d\n", surfaceparm.pixel_format); |
206 | |
207 | - surface = mir_surface_create_sync(connection, &surfaceparm); |
208 | + surface = mir_surface_create_sync(connection, &surfaceparm, &delegate); |
209 | CHECK(mir_surface_is_valid(surface), "Can't create a surface"); |
210 | |
211 | egldisplay = eglGetDisplay( |
212 | |
213 | === modified file 'examples/render_surfaces.cpp' |
214 | --- examples/render_surfaces.cpp 2013-04-02 09:36:09 +0000 |
215 | +++ examples/render_surfaces.cpp 2013-04-03 18:49:21 +0000 |
216 | @@ -23,7 +23,7 @@ |
217 | #include "mir/geometry/size.h" |
218 | #include "mir/graphics/buffer_initializer.h" |
219 | #include "mir/graphics/display.h" |
220 | -#include "mir/input/input_manager.h" |
221 | +#include "mir/input/null_input_manager.h" |
222 | #include "mir/shell/surface_builder.h" |
223 | #include "mir/surfaces/surface.h" |
224 | #include "mir/default_server_configuration.h" |
225 | @@ -380,20 +380,6 @@ |
226 | // Stub out input. |
227 | std::shared_ptr<mi::InputManager> RenderSurfacesServerConfiguration::the_input_manager() |
228 | { |
229 | - struct NullInputManager : public mi::InputManager |
230 | - { |
231 | - void start() {} |
232 | - void stop() {} |
233 | - std::shared_ptr<mi::InputChannel> make_input_channel() |
234 | - { |
235 | - return std::shared_ptr<mi::InputChannel>(); |
236 | - } |
237 | - void set_input_focus_to(std::shared_ptr<mi::SessionTarget> const& /* session */, |
238 | - std::shared_ptr<mi::SurfaceTarget> const& /* surface */) |
239 | - { |
240 | - } |
241 | - }; |
242 | - |
243 | - return std::make_shared<NullInputManager>(); |
244 | + return std::make_shared<mi::NullInputManager>(); |
245 | } |
246 | ///\internal [NullInputManager_tag] |
247 | |
248 | === modified file 'include/client/mir_toolkit/mir_client_library.h' |
249 | --- include/client/mir_toolkit/mir_client_library.h 2013-03-29 11:39:30 +0000 |
250 | +++ include/client/mir_toolkit/mir_client_library.h 2013-04-03 18:49:21 +0000 |
251 | @@ -124,6 +124,7 @@ |
252 | MirWaitHandle *mir_surface_create( |
253 | MirConnection *connection, |
254 | MirSurfaceParameters const *surface_parameters, |
255 | + MirEventDelegate const *event_handler, |
256 | mir_surface_lifecycle_callback callback, |
257 | void *context); |
258 | |
259 | @@ -135,7 +136,8 @@ |
260 | * \return The resulting surface |
261 | */ |
262 | MirSurface *mir_surface_create_sync(MirConnection *connection, |
263 | - MirSurfaceParameters const *params); |
264 | + MirSurfaceParameters const *params, |
265 | + MirEventDelegate const *event_handler); |
266 | |
267 | /** |
268 | * Get a window type that can be used for OpenGL ES 2.0 acceleration. |
269 | |
270 | === added file 'include/server/mir/input/null_input_manager.h' |
271 | --- include/server/mir/input/null_input_manager.h 1970-01-01 00:00:00 +0000 |
272 | +++ include/server/mir/input/null_input_manager.h 2013-04-03 18:49:21 +0000 |
273 | @@ -0,0 +1,56 @@ |
274 | +/* |
275 | + * Copyright © 2013 Canonical Ltd. |
276 | + * |
277 | + * This program is free software: you can redistribute it and/or modify it |
278 | + * under the terms of the GNU Lesser General Public License version 3, |
279 | + * as published by the Free Software Foundation. |
280 | + * |
281 | + * This program is distributed in the hope that it will be useful, |
282 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
283 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
284 | + * GNU General Public License for more details. |
285 | + * |
286 | + * You should have received a copy of the GNU Lesser General Public License |
287 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
288 | + * |
289 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
290 | + */ |
291 | + |
292 | +#ifndef MIR_INPUT_NULL_INPUT_MANAGER_H_ |
293 | +#define MIR_INPUT_NULL_INPUT_MANAGER_H_ |
294 | + |
295 | +#include "mir/input/input_manager.h" |
296 | + |
297 | +namespace mir |
298 | +{ |
299 | +namespace input |
300 | +{ |
301 | + |
302 | +class NullInputManager : public InputManager |
303 | +{ |
304 | +public: |
305 | + NullInputManager() {}; |
306 | + virtual ~NullInputManager() {} |
307 | + |
308 | + void start() {} |
309 | + void stop() {} |
310 | + |
311 | + std::shared_ptr<InputChannel> make_input_channel() |
312 | + { |
313 | + return std::shared_ptr<InputChannel>(); |
314 | + } |
315 | + |
316 | + virtual void set_input_focus_to(std::shared_ptr<input::SessionTarget> const& /* session */, |
317 | + std::shared_ptr<input::SurfaceTarget> const& /* surface */) |
318 | + { |
319 | + } |
320 | + |
321 | +protected: |
322 | + NullInputManager(const NullInputManager&) = delete; |
323 | + NullInputManager& operator=(const NullInputManager&) = delete; |
324 | +}; |
325 | + |
326 | +} |
327 | +} |
328 | + |
329 | +#endif // MIR_INPUT_NULL_INPUT_MANAGER |
330 | |
331 | === added directory 'include/shared/mir/input' |
332 | === added directory 'include/shared/mir/input/android' |
333 | === renamed file 'src/server/input/android/android_input_lexicon.h' => 'include/shared/mir/input/android/android_input_lexicon.h' |
334 | --- src/server/input/android/android_input_lexicon.h 2013-03-13 04:54:15 +0000 |
335 | +++ include/shared/mir/input/android/android_input_lexicon.h 2013-04-03 18:49:21 +0000 |
336 | @@ -35,11 +35,18 @@ |
337 | { |
338 | namespace android |
339 | { |
340 | +namespace transport |
341 | +{ |
342 | + |
343 | +/// The Lexicon translates droidinput event types to MirEvent types prior to |
344 | +/// shell or client handling. |
345 | class Lexicon |
346 | { |
347 | public: |
348 | static void translate(const droidinput::InputEvent *android_event, MirEvent &mir_event); |
349 | }; |
350 | + |
351 | +} |
352 | } |
353 | } |
354 | } |
355 | |
356 | === modified file 'include/shared/mir_toolkit/c_types.h' |
357 | --- include/shared/mir_toolkit/c_types.h 2013-03-29 11:27:00 +0000 |
358 | +++ include/shared/mir_toolkit/c_types.h 2013-04-03 18:49:21 +0000 |
359 | @@ -19,6 +19,8 @@ |
360 | #ifndef MIR_TOOLKIT_C_TYPES_H_ |
361 | #define MIR_TOOLKIT_C_TYPES_H_ |
362 | |
363 | +#include <mir_toolkit/input/event.h> |
364 | + |
365 | #ifdef __cplusplus |
366 | /** |
367 | * \defgroup mir_toolkit MIR graphics tools API |
368 | @@ -60,6 +62,15 @@ |
369 | typedef void (*mir_surface_lifecycle_callback)(MirSurface *surface, void *client_context); |
370 | |
371 | /** |
372 | + * Callback member of MirEventDelegate for handling of input events. |
373 | + * \param [in] surface The surface on which an event has occurred |
374 | + * \param [in] event The event to be handled |
375 | + * \param [in,out] context The context provided by client during delegate |
376 | + * registration. |
377 | + */ |
378 | +typedef void (*mir_event_delegate_handle_input_callback)(MirSurface* surface, MirEvent* ev, void* context); |
379 | + |
380 | +/** |
381 | * The order of components in a format enum matches the |
382 | * order of the components as they would be written in an |
383 | * integer representing a pixel value of that format. |
384 | @@ -158,6 +169,16 @@ |
385 | MirPixelFormat supported_pixel_format[mir_supported_pixel_format_max]; |
386 | } MirDisplayInfo; |
387 | |
388 | +/** |
389 | + * MirEventDelegate may be used to specify (at surface creation time) callbacks for |
390 | + * handling of input events |
391 | + */ |
392 | +typedef struct MirEventDelegate |
393 | +{ |
394 | + mir_event_delegate_handle_input_callback handle_input; |
395 | + void *context; |
396 | +} MirEventDelegate; |
397 | + |
398 | #ifdef __cplusplus |
399 | } |
400 | /**@}*/ |
401 | |
402 | === modified file 'include/shared/mir_toolkit/input/event.h' |
403 | --- include/shared/mir_toolkit/input/event.h 2013-03-29 11:39:30 +0000 |
404 | +++ include/shared/mir_toolkit/input/event.h 2013-04-03 18:49:21 +0000 |
405 | @@ -41,7 +41,7 @@ |
406 | MIR_INPUT_EVENT_TYPE_HW_SWITCH |
407 | } MirEventType; |
408 | |
409 | - struct MirEvent |
410 | + typedef struct MirEvent |
411 | { |
412 | /* Generic event properties */ |
413 | MirEventType type; |
414 | @@ -94,7 +94,7 @@ |
415 | } pointer_coordinates[MIR_INPUT_EVENT_MAX_POINTER_COUNT]; |
416 | } motion; |
417 | } details; |
418 | - }; |
419 | + } MirEvent; |
420 | |
421 | #ifdef __cplusplus |
422 | } |
423 | |
424 | === modified file 'include/test/mir_test/wait_condition.h' |
425 | --- include/test/mir_test/wait_condition.h 2013-03-22 16:41:59 +0000 |
426 | +++ include/test/mir_test/wait_condition.h 2013-04-03 18:49:21 +0000 |
427 | @@ -19,12 +19,16 @@ |
428 | #ifndef MIR_TEST_WAIT_CONDITION_H_ |
429 | #define MIR_TEST_WAIT_CONDITION_H_ |
430 | |
431 | +#include <gmock/gmock.h> |
432 | + |
433 | #include <chrono> |
434 | #include <mutex> |
435 | #include <condition_variable> |
436 | |
437 | namespace mir |
438 | { |
439 | +namespace test |
440 | +{ |
441 | struct WaitCondition |
442 | { |
443 | WaitCondition() : woken(false) {} |
444 | @@ -46,10 +50,7 @@ |
445 | std::condition_variable condition; |
446 | bool woken; |
447 | }; |
448 | -} |
449 | |
450 | -namespace |
451 | -{ |
452 | ACTION_P(ReturnFalseAndWakeUp, wait_condition) |
453 | { |
454 | wait_condition->wake_up_everyone(); |
455 | @@ -60,5 +61,6 @@ |
456 | wait_condition->wake_up_everyone(); |
457 | } |
458 | } |
459 | +} |
460 | |
461 | #endif // MIR_TEST_WAIT_CONDITION_H_ |
462 | |
463 | === modified file 'src/client/CMakeLists.txt' |
464 | --- src/client/CMakeLists.txt 2013-03-29 22:30:35 +0000 |
465 | +++ src/client/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
466 | @@ -35,6 +35,7 @@ |
467 | mir_basic_rpc_channel.cpp |
468 | ${PROTO_SRCS} |
469 | ) |
470 | +add_subdirectory(input) |
471 | |
472 | list(APPEND CLIENT_SOURCES |
473 | mir_socket_rpc_channel.cpp |
474 | @@ -82,15 +83,15 @@ |
475 | SOVERSION ${MIR_VERSION_MAJOR} |
476 | ) |
477 | |
478 | -target_link_libraries( |
479 | - mirclient |
480 | - |
481 | +set( |
482 | + MIR_CLIENT_LIBRARIES |
483 | ${Boost_LIBRARIES} |
484 | ${CMAKE_THREAD_LIBS_INIT} |
485 | ${LIBHARDWARE_LIBRARIES} |
486 | ${PROTOBUF_LIBRARIES} |
487 | |
488 | mirprotobuf |
489 | + mirinputandroidtransport |
490 | |
491 | ${DRM_LIBRARIES} |
492 | ${MIR_COMMON_PLATFORM_LIBRARIES} |
493 | @@ -98,6 +99,12 @@ |
494 | 3rd_party |
495 | ) |
496 | |
497 | +target_link_libraries( |
498 | + mirclient |
499 | + |
500 | + ${MIR_CLIENT_LIBRARIES} |
501 | +) |
502 | + |
503 | install( |
504 | TARGETS mirclient |
505 | LIBRARY DESTINATION lib |
506 | |
507 | === added directory 'src/client/input' |
508 | === added file 'src/client/input/CMakeLists.txt' |
509 | --- src/client/input/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
510 | +++ src/client/input/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
511 | @@ -0,0 +1,12 @@ |
512 | +list( |
513 | + APPEND CLIENT_SOURCES |
514 | + ${CMAKE_CURRENT_SOURCE_DIR}/android_input_receiver.cpp |
515 | + ${CMAKE_CURRENT_SOURCE_DIR}/android_input_receiver_thread.cpp |
516 | + ${CMAKE_CURRENT_SOURCE_DIR}/android_input_platform.cpp |
517 | +) |
518 | + |
519 | +set( |
520 | + CLIENT_SOURCES |
521 | + ${CLIENT_SOURCES} |
522 | + PARENT_SCOPE |
523 | +) |
524 | |
525 | === added file 'src/client/input/android_input_platform.cpp' |
526 | --- src/client/input/android_input_platform.cpp 1970-01-01 00:00:00 +0000 |
527 | +++ src/client/input/android_input_platform.cpp 2013-04-03 18:49:21 +0000 |
528 | @@ -0,0 +1,44 @@ |
529 | +/* |
530 | + * Copyright © 2013 Canonical Ltd. |
531 | + * |
532 | + * This program is free software: you can redistribute it and/or modify |
533 | + * it under the terms of the GNU General Public License version 3 as |
534 | + * published by the Free Software Foundation. |
535 | + * |
536 | + * This program is distributed in the hope that it will be useful, |
537 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
538 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
539 | + * GNU General Public License for more details. |
540 | + * |
541 | + * You should have received a copy of the GNU General Public License |
542 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
543 | + * |
544 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
545 | + */ |
546 | + |
547 | +#include "android_input_platform.h" |
548 | +#include "android_input_receiver.h" |
549 | +#include "android_input_receiver_thread.h" |
550 | + |
551 | +namespace mcli = mir::client::input; |
552 | +namespace mclia = mcli::android; |
553 | + |
554 | +mclia::AndroidInputPlatform::AndroidInputPlatform() |
555 | +{ |
556 | +} |
557 | + |
558 | +mclia::AndroidInputPlatform::~AndroidInputPlatform() |
559 | +{ |
560 | +} |
561 | + |
562 | +std::shared_ptr<mcli::InputReceiverThread> mclia::AndroidInputPlatform::create_input_thread( |
563 | + int fd, std::function<void(MirEvent*)> const& callback) |
564 | +{ |
565 | + auto receiver = std::make_shared<mclia::InputReceiver>(fd); |
566 | + return std::make_shared<mclia::InputReceiverThread>(receiver, callback); |
567 | +} |
568 | + |
569 | +std::shared_ptr<mcli::InputPlatform> mcli::InputPlatform::create() |
570 | +{ |
571 | + return std::make_shared<mclia::AndroidInputPlatform>(); |
572 | +} |
573 | |
574 | === added file 'src/client/input/android_input_platform.h' |
575 | --- src/client/input/android_input_platform.h 1970-01-01 00:00:00 +0000 |
576 | +++ src/client/input/android_input_platform.h 2013-04-03 18:49:21 +0000 |
577 | @@ -0,0 +1,52 @@ |
578 | +/* |
579 | + * Copyright © 2013 Canonical Ltd. |
580 | + * |
581 | + * This program is free software: you can redistribute it and/or modify |
582 | + * it under the terms of the GNU General Public License version 3 as |
583 | + * published by the Free Software Foundation. |
584 | + * |
585 | + * This program is distributed in the hope that it will be useful, |
586 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
587 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
588 | + * GNU General Public License for more details. |
589 | + * |
590 | + * You should have received a copy of the GNU General Public License |
591 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
592 | + * |
593 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
594 | + */ |
595 | + |
596 | +#ifndef MIR_CLIENT_ANDROID_INPUT_PLATFORM_H_ |
597 | +#define MIR_CLIENT_ANDROID_INPUT_PLATFORM_H_ |
598 | + |
599 | +#include "input_platform.h" |
600 | + |
601 | +namespace mir |
602 | +{ |
603 | +namespace client |
604 | +{ |
605 | +namespace input |
606 | +{ |
607 | +namespace android |
608 | +{ |
609 | + |
610 | +/// Implementation of client input machinery for android input stack wire protocol. |
611 | +class AndroidInputPlatform : public InputPlatform |
612 | +{ |
613 | +public: |
614 | + AndroidInputPlatform(); |
615 | + virtual ~AndroidInputPlatform(); |
616 | + |
617 | + std::shared_ptr<InputReceiverThread> create_input_thread(int fd, std::function<void(MirEvent *)> const& callback); |
618 | + |
619 | +protected: |
620 | + AndroidInputPlatform(const AndroidInputPlatform&) = delete; |
621 | + AndroidInputPlatform& operator=(const AndroidInputPlatform&) = delete; |
622 | +}; |
623 | + |
624 | +} |
625 | +} |
626 | +} |
627 | +} // namespace mir |
628 | + |
629 | +#endif // MIR_CLIENT_ANDROID_INPUT_PLATFORM_H_ |
630 | |
631 | === added file 'src/client/input/android_input_receiver.cpp' |
632 | --- src/client/input/android_input_receiver.cpp 1970-01-01 00:00:00 +0000 |
633 | +++ src/client/input/android_input_receiver.cpp 2013-04-03 18:49:21 +0000 |
634 | @@ -0,0 +1,91 @@ |
635 | +/* |
636 | + * Copyright © 2013 Canonical Ltd. |
637 | + * |
638 | + * This program is free software: you can redistribute it and/or modify |
639 | + * it under the terms of the GNU General Public License version 3 as |
640 | + * published by the Free Software Foundation. |
641 | + * |
642 | + * This program is distributed in the hope that it will be useful, |
643 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
644 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
645 | + * GNU General Public License for more details. |
646 | + * |
647 | + * You should have received a copy of the GNU General Public License |
648 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
649 | + * |
650 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
651 | + */ |
652 | + |
653 | +#include "android_input_receiver.h" |
654 | +#include "mir/input/android/android_input_lexicon.h" |
655 | + |
656 | +#include <androidfw/InputTransport.h> |
657 | +#include <utils/Looper.h> |
658 | + |
659 | +namespace mclia = mir::client::input::android; |
660 | +namespace miat = mir::input::android::transport; |
661 | + |
662 | +mclia::InputReceiver::InputReceiver(droidinput::sp<droidinput::InputChannel> const& input_channel) |
663 | + : input_channel(input_channel), |
664 | + input_consumer(std::make_shared<droidinput::InputConsumer>(input_channel)), |
665 | + looper(new droidinput::Looper(true)), |
666 | + fd_added(false) |
667 | +{ |
668 | +} |
669 | + |
670 | +mclia::InputReceiver::InputReceiver(int fd) |
671 | + : input_channel(new droidinput::InputChannel(droidinput::String8(""), fd)), |
672 | + input_consumer(std::make_shared<droidinput::InputConsumer>(input_channel)), |
673 | + looper(new droidinput::Looper(true)), |
674 | + fd_added(false) |
675 | +{ |
676 | +} |
677 | + |
678 | +mclia::InputReceiver::~InputReceiver() |
679 | +{ |
680 | +} |
681 | + |
682 | +int mclia::InputReceiver::fd() const |
683 | +{ |
684 | + return input_channel->getFd(); |
685 | +} |
686 | + |
687 | +// TODO: We use a droidinput::Looper here for polling functionality but it might be nice to integrate |
688 | +// with the existing client io_service ~racarr ~tvoss |
689 | +bool mclia::InputReceiver::next_event(std::chrono::milliseconds const& timeout, MirEvent &ev) |
690 | +{ |
691 | + droidinput::InputEvent *android_event; |
692 | + uint32_t event_sequence_id; |
693 | + bool handled_event = false; |
694 | + |
695 | + if (!fd_added) |
696 | + { |
697 | + // TODO: Why will this fail from the constructor? ~racarr |
698 | + looper->addFd(fd(), fd(), ALOOPER_EVENT_INPUT, nullptr, nullptr); |
699 | + fd_added = true; |
700 | + } |
701 | + |
702 | + auto result = looper->pollOnce(timeout.count()); |
703 | + if (result == ALOOPER_POLL_WAKE) |
704 | + return false; |
705 | + else if (result == ALOOPER_POLL_ERROR) // TODO: Exception? |
706 | + return false; |
707 | + |
708 | + if(input_consumer->consume(&event_factory, true, |
709 | + -1, &event_sequence_id, &android_event) != droidinput::WOULD_BLOCK) |
710 | + { |
711 | + miat::Lexicon::translate(android_event, ev); |
712 | + input_consumer->sendFinishedSignal(event_sequence_id, true); |
713 | + handled_event = true; |
714 | + } |
715 | + |
716 | + // So far once we have sent an event to the client there is no chance for redispatch |
717 | + // so the client handles all events. |
718 | + |
719 | + return handled_event; |
720 | +} |
721 | + |
722 | +void mclia::InputReceiver::wake() |
723 | +{ |
724 | + looper->wake(); |
725 | +} |
726 | |
727 | === added file 'src/client/input/android_input_receiver.h' |
728 | --- src/client/input/android_input_receiver.h 1970-01-01 00:00:00 +0000 |
729 | +++ src/client/input/android_input_receiver.h 2013-04-03 18:49:21 +0000 |
730 | @@ -0,0 +1,84 @@ |
731 | +/* |
732 | + * Copyright © 2013 Canonical Ltd. |
733 | + * |
734 | + * This program is free software: you can redistribute it and/or modify |
735 | + * it under the terms of the GNU General Public License version 3 as |
736 | + * published by the Free Software Foundation. |
737 | + * |
738 | + * This program is distributed in the hope that it will be useful, |
739 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
740 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
741 | + * GNU General Public License for more details. |
742 | + * |
743 | + * You should have received a copy of the GNU General Public License |
744 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
745 | + * |
746 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
747 | + */ |
748 | + |
749 | +#ifndef MIR_INPUT_ANDROID_INPUT_RECEIVER_H_ |
750 | +#define MIR_INPUT_ANDROID_INPUT_RECEIVER_H_ |
751 | + |
752 | +#include "mir_toolkit/input/event.h" |
753 | + |
754 | +#include <utils/StrongPointer.h> |
755 | +#include <androidfw/Input.h> |
756 | + |
757 | +#include <memory> |
758 | +#include <chrono> |
759 | + |
760 | +namespace droidinput = android; |
761 | + |
762 | +namespace android |
763 | +{ |
764 | +class InputChannel; |
765 | +class InputConsumer; |
766 | +class Looper; |
767 | +} |
768 | + |
769 | +namespace mir |
770 | +{ |
771 | +namespace client |
772 | +{ |
773 | +namespace input |
774 | +{ |
775 | +namespace android |
776 | +{ |
777 | + |
778 | +/// Synchronously receives input events in a blocking manner |
779 | +class InputReceiver |
780 | +{ |
781 | +public: |
782 | + InputReceiver(droidinput::sp<droidinput::InputChannel> const& input_channel); |
783 | + InputReceiver(int fd); |
784 | + |
785 | + virtual ~InputReceiver(); |
786 | + int fd() const; |
787 | + |
788 | + /// Synchronously receive an event with millisecond timeout. A negative timeout value |
789 | + /// is used to request indefinite polling. |
790 | + virtual bool next_event(std::chrono::milliseconds const& timeout, MirEvent &ev); |
791 | + virtual bool next_event(MirEvent &ev) { return next_event(std::chrono::milliseconds(-1), ev); } |
792 | + |
793 | + /// May be used from any thread to wake an InputReceiver blocked in next_event |
794 | + virtual void wake(); |
795 | + |
796 | +protected: |
797 | + InputReceiver(const InputReceiver&) = delete; |
798 | + InputReceiver& operator=(const InputReceiver&) = delete; |
799 | + |
800 | +private: |
801 | + droidinput::sp<droidinput::InputChannel> input_channel; |
802 | + std::shared_ptr<droidinput::InputConsumer> input_consumer; |
803 | + droidinput::PreallocatedInputEventFactory event_factory; |
804 | + droidinput::sp<droidinput::Looper> looper; |
805 | + |
806 | + bool fd_added; |
807 | +}; |
808 | + |
809 | +} |
810 | +} |
811 | +} |
812 | +} // namespace mir |
813 | + |
814 | +#endif // MIR_INPUT_ANDROID_INPUT_RECEIVER_H_ |
815 | |
816 | === added file 'src/client/input/android_input_receiver_thread.cpp' |
817 | --- src/client/input/android_input_receiver_thread.cpp 1970-01-01 00:00:00 +0000 |
818 | +++ src/client/input/android_input_receiver_thread.cpp 2013-04-03 18:49:21 +0000 |
819 | @@ -0,0 +1,68 @@ |
820 | +/* |
821 | + * Copyright © 2013 Canonical Ltd. |
822 | + * |
823 | + * This program is free software: you can redistribute it and/or modify |
824 | + * it under the terms of the GNU General Public License version 3 as |
825 | + * published by the Free Software Foundation. |
826 | + * |
827 | + * This program is distributed in the hope that it will be useful, |
828 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
829 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
830 | + * GNU General Public License for more details. |
831 | + * |
832 | + * You should have received a copy of the GNU General Public License |
833 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
834 | + * |
835 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
836 | + */ |
837 | + |
838 | +#include "android_input_receiver_thread.h" |
839 | +#include "android_input_receiver.h" |
840 | + |
841 | +#include <thread> |
842 | + |
843 | +namespace mclia = mir::client::input::android; |
844 | + |
845 | +mclia::InputReceiverThread::InputReceiverThread(std::shared_ptr<mclia::InputReceiver> const& receiver, |
846 | + std::function<void(MirEvent*)> const& event_handling_callback) |
847 | + : receiver(receiver), |
848 | + handler(event_handling_callback), |
849 | + running(false) |
850 | +{ |
851 | +} |
852 | + |
853 | +mclia::InputReceiverThread::~InputReceiverThread() |
854 | +{ |
855 | + if (running) |
856 | + stop(); |
857 | + if (thread.joinable()) |
858 | + join(); |
859 | +} |
860 | + |
861 | +void mclia::InputReceiverThread::start() |
862 | +{ |
863 | + running = true; |
864 | + thread = std::thread(std::mem_fn(&mclia::InputReceiverThread::thread_loop), this); |
865 | +} |
866 | + |
867 | +void mclia::InputReceiverThread::stop() |
868 | +{ |
869 | + running = false; |
870 | + receiver->wake(); |
871 | +} |
872 | + |
873 | +void mclia::InputReceiverThread::join() |
874 | +{ |
875 | + thread.join(); |
876 | +} |
877 | + |
878 | +void mclia::InputReceiverThread::thread_loop() |
879 | +{ |
880 | + while (running) |
881 | + { |
882 | + MirEvent ev; |
883 | + while(running && receiver->next_event(ev)) |
884 | + handler(&ev); |
885 | + std::this_thread::yield(); // yield() is needed to ensure reasonable runtime under valgrind |
886 | + } |
887 | +} |
888 | |
889 | === added file 'src/client/input/android_input_receiver_thread.h' |
890 | --- src/client/input/android_input_receiver_thread.h 1970-01-01 00:00:00 +0000 |
891 | +++ src/client/input/android_input_receiver_thread.h 2013-04-03 18:49:21 +0000 |
892 | @@ -0,0 +1,71 @@ |
893 | +/* |
894 | + * Copyright © 2013 Canonical Ltd. |
895 | + * |
896 | + * This program is free software: you can redistribute it and/or modify |
897 | + * it under the terms of the GNU General Public License version 3 as |
898 | + * 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_ANDROID_INPUT_RECEIVER_THREAD_H_ |
912 | +#define MIR_INPUT_ANDROID_INPUT_RECEIVER_THREAD_H_ |
913 | + |
914 | +#include "input_receiver_thread.h" |
915 | + |
916 | +#include "mir_toolkit/input/event.h" |
917 | + |
918 | +#include <functional> |
919 | +#include <memory> |
920 | +#include <atomic> |
921 | +#include <thread> |
922 | + |
923 | +namespace mir |
924 | +{ |
925 | +namespace client |
926 | +{ |
927 | +namespace input |
928 | +{ |
929 | +namespace android |
930 | +{ |
931 | +class InputReceiver; |
932 | + |
933 | +/// Responsible for polling an InputReceiver to read and dispatch events when appropriate. |
934 | +class InputReceiverThread : public input::InputReceiverThread |
935 | +{ |
936 | +public: |
937 | + InputReceiverThread(std::shared_ptr<InputReceiver> const& receiver, |
938 | + std::function<void(MirEvent*)> const& event_handling_callback); |
939 | + virtual ~InputReceiverThread(); |
940 | + |
941 | + void start(); |
942 | + void stop(); |
943 | + void join(); |
944 | + |
945 | +protected: |
946 | + InputReceiverThread(const InputReceiverThread&) = delete; |
947 | + InputReceiverThread& operator=(const InputReceiverThread&) = delete; |
948 | + |
949 | +private: |
950 | + std::shared_ptr<InputReceiver> const receiver; |
951 | + std::function<void(MirEvent*)> const handler; |
952 | + |
953 | + void thread_loop(); |
954 | + std::atomic<bool> running; |
955 | + std::thread thread; |
956 | +}; |
957 | + |
958 | +} |
959 | +} |
960 | +} |
961 | +} // namespace mir |
962 | + |
963 | +#endif // MIR_INPUT_ANDROID_INPUT_RECEIVER_THREAD_H_ |
964 | |
965 | === added file 'src/client/input/input_platform.h' |
966 | --- src/client/input/input_platform.h 1970-01-01 00:00:00 +0000 |
967 | +++ src/client/input/input_platform.h 2013-04-03 18:49:21 +0000 |
968 | @@ -0,0 +1,55 @@ |
969 | +/* |
970 | + * Copyright © 2013 Canonical Ltd. |
971 | + * |
972 | + * This program is free software: you can redistribute it and/or modify |
973 | + * it under the terms of the GNU General Public License version 3 as |
974 | + * published by the Free Software Foundation. |
975 | + * |
976 | + * This program is distributed in the hope that it will be useful, |
977 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
978 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
979 | + * GNU General Public License for more details. |
980 | + * |
981 | + * You should have received a copy of the GNU General Public License |
982 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
983 | + * |
984 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
985 | + */ |
986 | + |
987 | +#ifndef MIR_CLIENT_INPUT_PLATFORM_H_ |
988 | +#define MIR_CLIENT_INPUT_PLATFORM_H_ |
989 | + |
990 | +#include "mir_toolkit/input/event.h" |
991 | + |
992 | +#include <memory> |
993 | +#include <functional> |
994 | + |
995 | +namespace mir |
996 | +{ |
997 | +namespace client |
998 | +{ |
999 | +namespace input |
1000 | +{ |
1001 | +class InputReceiverThread; |
1002 | + |
1003 | +// Interface for MirSurface to construct input dispatcher threads. |
1004 | +class InputPlatform |
1005 | +{ |
1006 | +public: |
1007 | + virtual ~InputPlatform() {}; |
1008 | + |
1009 | + virtual std::shared_ptr<InputReceiverThread> create_input_thread(int fd, std::function<void(MirEvent *)> const& callback) = 0; |
1010 | + |
1011 | + static std::shared_ptr<InputPlatform> create(); |
1012 | + |
1013 | +protected: |
1014 | + InputPlatform() = default; |
1015 | + InputPlatform(const InputPlatform&) = delete; |
1016 | + InputPlatform& operator=(const InputPlatform&) = delete; |
1017 | +}; |
1018 | + |
1019 | +} |
1020 | +} |
1021 | +} // namespace mir |
1022 | + |
1023 | +#endif // MIR_CLIENT_INPUT_PLATFORM_H_ |
1024 | |
1025 | === added file 'src/client/input/input_receiver_thread.h' |
1026 | --- src/client/input/input_receiver_thread.h 1970-01-01 00:00:00 +0000 |
1027 | +++ src/client/input/input_receiver_thread.h 2013-04-03 18:49:21 +0000 |
1028 | @@ -0,0 +1,48 @@ |
1029 | +/* |
1030 | + * Copyright © 2013 Canonical Ltd. |
1031 | + * |
1032 | + * This program is free software: you can redistribute it and/or modify |
1033 | + * it under the terms of the GNU General Public License version 3 as |
1034 | + * published by the Free Software Foundation. |
1035 | + * |
1036 | + * This program is distributed in the hope that it will be useful, |
1037 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1038 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1039 | + * GNU General Public License for more details. |
1040 | + * |
1041 | + * You should have received a copy of the GNU General Public License |
1042 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1043 | + * |
1044 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
1045 | + */ |
1046 | + |
1047 | +#ifndef MIR_CLIENT_INPUT_RECEIVER_THREAD_H_ |
1048 | +#define MIR_CLIENT_INPUT_RECEIVER_THREAD_H_ |
1049 | + |
1050 | +namespace mir |
1051 | +{ |
1052 | +namespace client |
1053 | +{ |
1054 | +namespace input |
1055 | +{ |
1056 | + |
1057 | +class InputReceiverThread |
1058 | +{ |
1059 | +public: |
1060 | + virtual ~InputReceiverThread() {}; |
1061 | + |
1062 | + virtual void start() = 0; |
1063 | + virtual void stop() = 0; |
1064 | + virtual void join() = 0; |
1065 | + |
1066 | +protected: |
1067 | + InputReceiverThread() = default; |
1068 | + InputReceiverThread(const InputReceiverThread&) = delete; |
1069 | + InputReceiverThread& operator=(const InputReceiverThread&) = delete; |
1070 | +}; |
1071 | + |
1072 | +} |
1073 | +} |
1074 | +} // namespace mir |
1075 | + |
1076 | +#endif // MIR_CLIENT_INPUT_RECEIVER_THREAD_H_ |
1077 | |
1078 | === modified file 'src/client/mir_client_library.cpp' |
1079 | --- src/client/mir_client_library.cpp 2013-03-29 11:27:00 +0000 |
1080 | +++ src/client/mir_client_library.cpp 2013-04-03 18:49:21 +0000 |
1081 | @@ -118,16 +118,17 @@ |
1082 | } |
1083 | |
1084 | MirWaitHandle* mir_surface_create( |
1085 | - MirConnection * connection, |
1086 | - MirSurfaceParameters const * params, |
1087 | + MirConnection* connection, |
1088 | + MirSurfaceParameters const* params, |
1089 | + MirEventDelegate const* delegate, |
1090 | mir_surface_lifecycle_callback callback, |
1091 | - void * context) |
1092 | + void* context) |
1093 | { |
1094 | if (&error_connection == connection) return 0; |
1095 | |
1096 | try |
1097 | { |
1098 | - return connection->create_surface(*params, callback, context); |
1099 | + return connection->create_surface(*params, delegate, callback, context); |
1100 | } |
1101 | catch (std::exception const&) |
1102 | { |
1103 | @@ -137,12 +138,15 @@ |
1104 | |
1105 | } |
1106 | |
1107 | -MirSurface *mir_surface_create_sync( |
1108 | - MirConnection *connection, MirSurfaceParameters const *params) |
1109 | +MirSurface* mir_surface_create_sync( |
1110 | + MirConnection* connection, |
1111 | + MirSurfaceParameters const* params, |
1112 | + MirEventDelegate const* delegate) |
1113 | { |
1114 | MirSurface *surface = nullptr; |
1115 | |
1116 | mir_wait_for(mir_surface_create(connection, params, |
1117 | + delegate, |
1118 | reinterpret_cast<mir_surface_lifecycle_callback>(assign_result), |
1119 | &surface)); |
1120 | |
1121 | |
1122 | === modified file 'src/client/mir_client_surface.h' |
1123 | --- src/client/mir_client_surface.h 2013-03-29 11:27:00 +0000 |
1124 | +++ src/client/mir_client_surface.h 2013-04-03 18:49:21 +0000 |
1125 | @@ -22,6 +22,7 @@ |
1126 | #include "mir_toolkit/mir_client_library.h" |
1127 | |
1128 | #include <memory> |
1129 | + |
1130 | namespace mir |
1131 | { |
1132 | namespace client |
1133 | |
1134 | === modified file 'src/client/mir_connection.cpp' |
1135 | --- src/client/mir_connection.cpp 2013-03-29 11:27:00 +0000 |
1136 | +++ src/client/mir_connection.cpp 2013-04-03 18:49:21 +0000 |
1137 | @@ -25,10 +25,13 @@ |
1138 | #include "client_buffer_depository.h" |
1139 | #include "make_rpc_channel.h" |
1140 | |
1141 | +#include "input/input_platform.h" |
1142 | + |
1143 | #include <thread> |
1144 | #include <cstddef> |
1145 | |
1146 | namespace mcl = mir::client; |
1147 | +namespace mcli = mcl::input; |
1148 | namespace mp = mir::protobuf; |
1149 | namespace gp = google::protobuf; |
1150 | |
1151 | @@ -46,7 +49,8 @@ |
1152 | channel(channel), |
1153 | server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL), |
1154 | log(log), |
1155 | - client_platform_factory(client_platform_factory) |
1156 | + client_platform_factory(client_platform_factory), |
1157 | + input_platform(mcli::InputPlatform::create()) |
1158 | { |
1159 | { |
1160 | std::lock_guard<std::mutex> lock(connection_guard); |
1161 | @@ -63,11 +67,13 @@ |
1162 | |
1163 | MirWaitHandle* MirConnection::create_surface( |
1164 | MirSurfaceParameters const & params, |
1165 | + MirEventDelegate const* delegate, |
1166 | mir_surface_lifecycle_callback callback, |
1167 | void * context) |
1168 | { |
1169 | auto null_log = std::make_shared<mir::client::NullLogger>(); |
1170 | - auto surface = new MirSurface(this, server, null_log, platform->create_buffer_factory(), params, callback, context); |
1171 | + auto surface = new MirSurface(this, server, null_log, platform->create_buffer_factory(), input_platform, params, delegate, callback, context); |
1172 | + |
1173 | return surface->get_create_wait_handle(); |
1174 | } |
1175 | |
1176 | |
1177 | === modified file 'src/client/mir_connection.h' |
1178 | --- src/client/mir_connection.h 2013-04-02 09:23:02 +0000 |
1179 | +++ src/client/mir_connection.h 2013-04-03 18:49:21 +0000 |
1180 | @@ -42,6 +42,10 @@ |
1181 | class Logger; |
1182 | class ClientBufferDepository; |
1183 | class ClientPlatformFactory; |
1184 | +namespace input |
1185 | +{ |
1186 | +class InputPlatform; |
1187 | +} |
1188 | } |
1189 | } |
1190 | |
1191 | @@ -60,6 +64,7 @@ |
1192 | |
1193 | MirWaitHandle* create_surface( |
1194 | MirSurfaceParameters const & params, |
1195 | + MirEventDelegate const* delegate, |
1196 | mir_surface_lifecycle_callback callback, |
1197 | void * context); |
1198 | MirWaitHandle* release_surface( |
1199 | @@ -114,6 +119,8 @@ |
1200 | std::shared_ptr<mir::client::ClientPlatform> platform; |
1201 | std::shared_ptr<EGLNativeDisplayType> native_display; |
1202 | |
1203 | + std::shared_ptr<mir::client::input::InputPlatform> const input_platform; |
1204 | + |
1205 | std::string error_message; |
1206 | |
1207 | MirWaitHandle connect_wait_handle; |
1208 | |
1209 | === modified file 'src/client/mir_surface.cpp' |
1210 | --- src/client/mir_surface.cpp 2013-04-02 09:23:02 +0000 |
1211 | +++ src/client/mir_surface.cpp 2013-04-03 18:49:21 +0000 |
1212 | @@ -21,11 +21,14 @@ |
1213 | #include "client_buffer.h" |
1214 | #include "mir_surface.h" |
1215 | #include "mir_connection.h" |
1216 | +#include "input/input_receiver_thread.h" |
1217 | +#include "input/input_platform.h" |
1218 | |
1219 | #include <cassert> |
1220 | |
1221 | namespace geom = mir::geometry; |
1222 | namespace mcl = mir::client; |
1223 | +namespace mcli = mir::client::input; |
1224 | namespace mp = mir::protobuf; |
1225 | namespace gp = google::protobuf; |
1226 | |
1227 | @@ -34,11 +37,14 @@ |
1228 | mp::DisplayServer::Stub & server, |
1229 | std::shared_ptr<mir::client::Logger> const& logger, |
1230 | std::shared_ptr<mcl::ClientBufferFactory> const& factory, |
1231 | - MirSurfaceParameters const& params, |
1232 | + std::shared_ptr<mcli::InputPlatform> const& input_platform, |
1233 | + MirSurfaceParameters const & params, |
1234 | + MirEventDelegate const* delegate, |
1235 | mir_surface_lifecycle_callback callback, void * context) |
1236 | : server(server), |
1237 | connection(allocating_connection), |
1238 | buffer_depository(std::make_shared<mcl::ClientBufferDepository>(factory, 3)), |
1239 | + input_platform(input_platform), |
1240 | logger(logger) |
1241 | { |
1242 | mir::protobuf::SurfaceParameters message; |
1243 | @@ -47,6 +53,9 @@ |
1244 | message.set_height(params.height); |
1245 | message.set_pixel_format(params.pixel_format); |
1246 | message.set_buffer_usage(params.buffer_usage); |
1247 | + |
1248 | + if (delegate) |
1249 | + handle_event_callback = std::bind(delegate->handle_input, this, std::placeholders::_1, delegate->context); |
1250 | |
1251 | server.create_surface(0, &message, &surface, gp::NewCallback(this, &MirSurface::created, callback, context)); |
1252 | |
1253 | @@ -57,6 +66,8 @@ |
1254 | |
1255 | MirSurface::~MirSurface() |
1256 | { |
1257 | + if (input_thread) |
1258 | + input_thread->stop(); |
1259 | release_cpu_region(); |
1260 | } |
1261 | |
1262 | @@ -166,6 +177,13 @@ |
1263 | accelerated_window = platform->create_egl_native_window(this); |
1264 | |
1265 | callback(this, context); |
1266 | + |
1267 | + if (surface.fd_size() > 0 && handle_event_callback) |
1268 | + { |
1269 | + input_thread = input_platform->create_input_thread(surface.fd(0), handle_event_callback); |
1270 | + input_thread->start(); |
1271 | + } |
1272 | + |
1273 | create_wait_handle.result_received(); |
1274 | } |
1275 | |
1276 | |
1277 | === modified file 'src/client/mir_surface.h' |
1278 | --- src/client/mir_surface.h 2013-03-29 11:27:00 +0000 |
1279 | +++ src/client/mir_surface.h 2013-04-03 18:49:21 +0000 |
1280 | @@ -30,12 +30,19 @@ |
1281 | #include "client_platform.h" |
1282 | |
1283 | #include <memory> |
1284 | +#include <functional> |
1285 | |
1286 | namespace mir |
1287 | { |
1288 | namespace client |
1289 | { |
1290 | class ClientBuffer; |
1291 | +namespace input |
1292 | +{ |
1293 | +class InputPlatform; |
1294 | +class InputReceiverThread; |
1295 | +} |
1296 | + |
1297 | struct MemoryRegion; |
1298 | } |
1299 | } |
1300 | @@ -51,7 +58,9 @@ |
1301 | mir::protobuf::DisplayServer::Stub & server, |
1302 | std::shared_ptr<mir::client::Logger> const& logger, |
1303 | std::shared_ptr<mir::client::ClientBufferFactory> const& buffer_factory, |
1304 | + std::shared_ptr<mir::client::input::InputPlatform> const& input_platform, |
1305 | MirSurfaceParameters const& params, |
1306 | + MirEventDelegate const* delegate, |
1307 | mir_surface_lifecycle_callback callback, void * context); |
1308 | |
1309 | ~MirSurface(); |
1310 | @@ -97,6 +106,7 @@ |
1311 | |
1312 | std::shared_ptr<mir::client::MemoryRegion> secured_region; |
1313 | std::shared_ptr<mir::client::ClientBufferDepository> buffer_depository; |
1314 | + std::shared_ptr<mir::client::input::InputPlatform> const input_platform; |
1315 | |
1316 | std::shared_ptr<mir::client::Logger> logger; |
1317 | std::shared_ptr<EGLNativeWindowType> accelerated_window; |
1318 | @@ -105,6 +115,9 @@ |
1319 | |
1320 | // Cache of latest SurfaceSettings returned from the server |
1321 | int attrib_cache[mir_surface_attrib_arraysize_]; |
1322 | + |
1323 | + std::function<void(MirEvent*)> handle_event_callback; |
1324 | + std::shared_ptr<mir::client::input::InputReceiverThread> input_thread; |
1325 | }; |
1326 | |
1327 | #endif /* MIR_CLIENT_PRIVATE_MIR_WAIT_HANDLE_H_ */ |
1328 | |
1329 | === modified file 'src/server/CMakeLists.txt' |
1330 | --- src/server/CMakeLists.txt 2013-03-29 10:44:42 +0000 |
1331 | +++ src/server/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
1332 | @@ -51,6 +51,7 @@ |
1333 | mirfrontend |
1334 | mirgraphics |
1335 | mirinput |
1336 | + mirinputandroidtransport |
1337 | mirsurfaces |
1338 | mirtime |
1339 | ) |
1340 | |
1341 | === modified file 'src/server/default_server_configuration.cpp' |
1342 | --- src/server/default_server_configuration.cpp 2013-03-28 14:20:06 +0000 |
1343 | +++ src/server/default_server_configuration.cpp 2013-04-03 18:49:21 +0000 |
1344 | @@ -44,6 +44,7 @@ |
1345 | #include "mir/graphics/buffer_initializer.h" |
1346 | #include "mir/graphics/null_display_report.h" |
1347 | #include "mir/input/input_manager.h" |
1348 | +#include "mir/input/null_input_manager.h" |
1349 | #include "mir/logging/logger.h" |
1350 | #include "mir/logging/dumb_console_logger.h" |
1351 | #include "mir/logging/glog_logger.h" |
1352 | @@ -140,6 +141,7 @@ |
1353 | "Environment variables capitalise long form with prefix \"MIR_SERVER_\" and \"_\" in place of \"-\""); |
1354 | desc.add_options() |
1355 | ("file,f", po::value<std::string>(), "Socket filename") |
1356 | + ("enable-input,i", po::value<bool>(), "Enable input. [bool:default=false]") |
1357 | (log_display, po::value<bool>(), "Log the Display report. [bool:default=false]") |
1358 | (log_app_mediator, po::value<bool>(), "Log the ApplicationMediator report. [bool:default=false]") |
1359 | (log_msg_processor, po::value<bool>(), "log the MessageProcessor report") |
1360 | @@ -316,9 +318,12 @@ |
1361 | mir::DefaultServerConfiguration::the_input_manager() |
1362 | { |
1363 | return input_manager( |
1364 | - [&, this]() |
1365 | + [&, this]() -> std::shared_ptr<mi::InputManager> |
1366 | { |
1367 | - return mi::create_input_manager(the_event_filters(), the_display()); |
1368 | + if (the_options()->get("enable-input", false)) |
1369 | + return mi::create_input_manager(the_event_filters(), the_display()); |
1370 | + else |
1371 | + return std::make_shared<mi::NullInputManager>(); |
1372 | }); |
1373 | } |
1374 | |
1375 | |
1376 | === modified file 'src/server/frontend/protobuf_message_processor.cpp' |
1377 | --- src/server/frontend/protobuf_message_processor.cpp 2013-03-22 03:33:00 +0000 |
1378 | +++ src/server/frontend/protobuf_message_processor.cpp 2013-04-03 18:49:21 +0000 |
1379 | @@ -73,12 +73,14 @@ |
1380 | |
1381 | void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, mir::protobuf::Surface* response) |
1382 | { |
1383 | - const auto& fd = response->has_buffer() ? |
1384 | + auto const& surface_fd = extract_fds_from(response); |
1385 | + const auto& buffer_fd = response->has_buffer() ? |
1386 | extract_fds_from(response->mutable_buffer()) : |
1387 | std::vector<int32_t>(); |
1388 | |
1389 | send_response(id, static_cast<google::protobuf::Message*>(response)); |
1390 | - sender->send_fds(fd); |
1391 | + sender->send_fds(surface_fd); |
1392 | + sender->send_fds(buffer_fd); |
1393 | resource_cache->free_resource(response); |
1394 | } |
1395 | |
1396 | |
1397 | === modified file 'src/server/input/CMakeLists.txt' |
1398 | --- src/server/input/CMakeLists.txt 2013-03-13 04:54:15 +0000 |
1399 | +++ src/server/input/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
1400 | @@ -4,14 +4,7 @@ |
1401 | event_filter_chain.cpp |
1402 | ) |
1403 | |
1404 | -if (NOT MIR_DISABLE_INPUT) |
1405 | add_subdirectory(android) |
1406 | -else() |
1407 | -list( |
1408 | - APPEND INPUT_SOURCES |
1409 | - dummy_input_manager.cpp |
1410 | -) |
1411 | -endif() |
1412 | |
1413 | add_library( |
1414 | mirinput STATIC |
1415 | |
1416 | === modified file 'src/server/input/android/CMakeLists.txt' |
1417 | --- src/server/input/android/CMakeLists.txt 2013-03-22 16:41:59 +0000 |
1418 | +++ src/server/input/android/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
1419 | @@ -3,7 +3,6 @@ |
1420 | ${CMAKE_CURRENT_SOURCE_DIR}/android_input_manager.cpp |
1421 | ${CMAKE_CURRENT_SOURCE_DIR}/android_input_reader_policy.cpp |
1422 | ${CMAKE_CURRENT_SOURCE_DIR}/android_pointer_controller.cpp |
1423 | - ${CMAKE_CURRENT_SOURCE_DIR}/android_input_lexicon.cpp |
1424 | ${CMAKE_CURRENT_SOURCE_DIR}/android_input_channel.cpp |
1425 | ${CMAKE_CURRENT_SOURCE_DIR}/rudimentary_input_reader_policy.cpp |
1426 | ${CMAKE_CURRENT_SOURCE_DIR}/event_filter_dispatcher_policy.cpp |
1427 | @@ -18,3 +17,4 @@ |
1428 | PARENT_SCOPE |
1429 | ) |
1430 | |
1431 | +add_subdirectory(transport) |
1432 | |
1433 | === modified file 'src/server/input/android/android_input_application_handle.cpp' |
1434 | --- src/server/input/android/android_input_application_handle.cpp 2013-03-20 22:42:09 +0000 |
1435 | +++ src/server/input/android/android_input_application_handle.cpp 2013-04-03 18:49:21 +0000 |
1436 | @@ -26,7 +26,7 @@ |
1437 | namespace mia = mi::android; |
1438 | |
1439 | mia::InputApplicationHandle::InputApplicationHandle(std::shared_ptr<mi::SessionTarget> const& session) |
1440 | - : session(session) |
1441 | + : weak_session(session) |
1442 | { |
1443 | updateInfo(); |
1444 | } |
1445 | @@ -35,6 +35,11 @@ |
1446 | { |
1447 | if (mInfo == NULL) |
1448 | mInfo = new droidinput::InputApplicationInfo; |
1449 | + |
1450 | + auto session = weak_session.lock(); |
1451 | + if (!session) |
1452 | + return false; |
1453 | + |
1454 | mInfo->dispatchingTimeout = INT_MAX; |
1455 | mInfo->name = droidinput::String8(session->name().c_str()); |
1456 | |
1457 | |
1458 | === modified file 'src/server/input/android/android_input_application_handle.h' |
1459 | --- src/server/input/android/android_input_application_handle.h 2013-03-20 22:42:09 +0000 |
1460 | +++ src/server/input/android/android_input_application_handle.h 2013-04-03 18:49:21 +0000 |
1461 | @@ -48,7 +48,7 @@ |
1462 | InputApplicationHandle& operator=(InputApplicationHandle const&) = delete; |
1463 | |
1464 | private: |
1465 | - std::shared_ptr<input::SessionTarget> session; |
1466 | + std::weak_ptr<input::SessionTarget> weak_session; |
1467 | }; |
1468 | |
1469 | } |
1470 | |
1471 | === modified file 'src/server/input/android/event_filter_dispatcher_policy.cpp' |
1472 | --- src/server/input/android/event_filter_dispatcher_policy.cpp 2013-03-22 16:41:59 +0000 |
1473 | +++ src/server/input/android/event_filter_dispatcher_policy.cpp 2013-04-03 18:49:21 +0000 |
1474 | @@ -16,10 +16,11 @@ |
1475 | * Authored by: Robert Carr <robert.carr@canonical.com> |
1476 | */ |
1477 | #include "event_filter_dispatcher_policy.h" |
1478 | -#include "android_input_lexicon.h" |
1479 | +#include "mir/input/android/android_input_lexicon.h" |
1480 | |
1481 | namespace mi = mir::input; |
1482 | namespace mia = mi::android; |
1483 | +namespace miat = mia::transport; |
1484 | |
1485 | mia::EventFilterDispatcherPolicy::EventFilterDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& event_filter) : |
1486 | event_filter(event_filter) |
1487 | @@ -29,7 +30,7 @@ |
1488 | bool mia::EventFilterDispatcherPolicy::filterInputEvent(const droidinput::InputEvent* input_event, uint32_t /*policy_flags*/) |
1489 | { |
1490 | MirEvent mir_ev; |
1491 | - mia::Lexicon::translate(input_event, mir_ev); |
1492 | + miat::Lexicon::translate(input_event, mir_ev); |
1493 | |
1494 | if (event_filter->handles(mir_ev)) |
1495 | return false; /* Do not pass the event on */ |
1496 | |
1497 | === added directory 'src/server/input/android/transport' |
1498 | === added file 'src/server/input/android/transport/CMakeLists.txt' |
1499 | --- src/server/input/android/transport/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1500 | +++ src/server/input/android/transport/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
1501 | @@ -0,0 +1,31 @@ |
1502 | +# Copyright © 2012 Canonical Ltd. |
1503 | +# |
1504 | +# This program is free software: you can redistribute it and/or modify |
1505 | +# it under the terms of the GNU General Public License version 3 as |
1506 | +# published by the Free Software Foundation. |
1507 | +# |
1508 | +# This program is distributed in the hope that it will be useful, |
1509 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1510 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1511 | +# GNU General Public License for more details. |
1512 | +# |
1513 | +# You should have received a copy of the GNU General Public License |
1514 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1515 | +# |
1516 | +# Authored by: Thomas Voss <thomas.voss@canonical.com> |
1517 | + |
1518 | +set( |
1519 | + ANDROID_TRANSPORT_SOURCES |
1520 | + ${CMAKE_CURRENT_SOURCE_DIR}/android_input_lexicon.cpp |
1521 | +) |
1522 | + |
1523 | +add_library( |
1524 | + mirinputandroidtransport STATIC |
1525 | + ${ANDROID_TRANSPORT_SOURCES} |
1526 | +) |
1527 | + |
1528 | +target_link_libraries( |
1529 | + mirinputandroidtransport |
1530 | + |
1531 | + android-input |
1532 | +) |
1533 | |
1534 | === renamed file 'src/server/input/android/android_input_lexicon.cpp' => 'src/server/input/android/transport/android_input_lexicon.cpp' |
1535 | --- src/server/input/android/android_input_lexicon.cpp 2013-03-13 04:54:15 +0000 |
1536 | +++ src/server/input/android/transport/android_input_lexicon.cpp 2013-04-03 18:49:21 +0000 |
1537 | @@ -1,29 +1,29 @@ |
1538 | /* |
1539 | * Copyright © 2012 Canonical Ltd. |
1540 | * |
1541 | - * This program is free software: you can redistribute it and/or modify it |
1542 | - * under the terms of the GNU Lesser General Public License version 3, |
1543 | - * as published by the Free Software Foundation. |
1544 | + * This program is free software: you can redistribute it and/or modify |
1545 | + * it under the terms of the GNU General Public License version 3 as |
1546 | + * published by the Free Software Foundation. |
1547 | * |
1548 | * This program is distributed in the hope that it will be useful, |
1549 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1550 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1551 | * GNU General Public License for more details. |
1552 | * |
1553 | - * You should have received a copy of the GNU Lesser General Public License |
1554 | + * You should have received a copy of the GNU General Public License |
1555 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1556 | * |
1557 | * Authored by: Thomas Voss <thomas.voss@canonical.com> |
1558 | * Robert Carr <robert.carr@canonical.com> |
1559 | */ |
1560 | |
1561 | -#include "android_input_lexicon.h" |
1562 | +#include "mir/input/android/android_input_lexicon.h" |
1563 | |
1564 | #include <androidfw/Input.h> |
1565 | |
1566 | -namespace mia = mir::input::android; |
1567 | +namespace miat = mir::input::android::transport; |
1568 | |
1569 | -void mia::Lexicon::translate(const droidinput::InputEvent *android_event, MirEvent &mir_event) |
1570 | +void miat::Lexicon::translate(const droidinput::InputEvent *android_event, MirEvent &mir_event) |
1571 | { |
1572 | switch(android_event->getType()) |
1573 | { |
1574 | |
1575 | === removed file 'src/server/input/dummy_input_manager.cpp' |
1576 | --- src/server/input/dummy_input_manager.cpp 2013-03-29 16:51:35 +0000 |
1577 | +++ src/server/input/dummy_input_manager.cpp 1970-01-01 00:00:00 +0000 |
1578 | @@ -1,42 +0,0 @@ |
1579 | -/* |
1580 | - * Copyright © 2012 Canonical Ltd. |
1581 | - * |
1582 | - * This program is free software: you can redistribute it and/or modify it |
1583 | - * under the terms of the GNU Lesser General Public License version 3, |
1584 | - * as published by the Free Software Foundation. |
1585 | - * |
1586 | - * This program is distributed in the hope that it will be useful, |
1587 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1588 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1589 | - * GNU General Public License for more details. |
1590 | - * |
1591 | - * You should have received a copy of the GNU Lesser General Public License |
1592 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1593 | - * |
1594 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
1595 | - */ |
1596 | - |
1597 | -#include "mir/input/input_manager.h" |
1598 | - |
1599 | -namespace mg = mir::graphics; |
1600 | -namespace mi = mir::input; |
1601 | - |
1602 | -namespace |
1603 | -{ |
1604 | -class DummyInputManager : public mi::InputManager |
1605 | -{ |
1606 | - void stop() {} |
1607 | - void start() {} |
1608 | - virtual std::shared_ptr<mi::InputChannel> make_input_channel() { return std::shared_ptr<mi::InputChannel>(); } |
1609 | - void set_input_focus_to(std::shared_ptr<mi::SessionTarget> const& /* session */, std::shared_ptr<mi::SurfaceTarget> const& /* surface */) |
1610 | - { |
1611 | - } |
1612 | -}; |
1613 | -} |
1614 | - |
1615 | -std::shared_ptr<mi::InputManager> mi::create_input_manager( |
1616 | - const std::initializer_list<std::shared_ptr<mi::EventFilter> const>& , |
1617 | - std::shared_ptr<mg::ViewableArea> const& ) |
1618 | -{ |
1619 | - return std::make_shared<DummyInputManager>(); |
1620 | -} |
1621 | |
1622 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
1623 | --- tests/acceptance-tests/CMakeLists.txt 2013-03-29 22:30:35 +0000 |
1624 | +++ tests/acceptance-tests/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
1625 | @@ -13,6 +13,9 @@ |
1626 | ) |
1627 | |
1628 | list(APPEND SOURCES |
1629 | + test_client_input.cpp) |
1630 | + |
1631 | +list(APPEND SOURCES |
1632 | test_server_startup.cpp |
1633 | ) |
1634 | |
1635 | @@ -21,6 +24,7 @@ |
1636 | |
1637 | ${SOURCES} |
1638 | ) |
1639 | +uses_android_input(acceptance-tests) |
1640 | |
1641 | |
1642 | target_link_libraries( |
1643 | |
1644 | === added file 'tests/acceptance-tests/test_client_input.cpp' |
1645 | --- tests/acceptance-tests/test_client_input.cpp 1970-01-01 00:00:00 +0000 |
1646 | +++ tests/acceptance-tests/test_client_input.cpp 2013-04-03 18:49:21 +0000 |
1647 | @@ -0,0 +1,268 @@ |
1648 | +/* |
1649 | + * Copyright © 2013 Canonical Ltd. |
1650 | + * |
1651 | + * This program is free software: you can redistribute it and/or modify |
1652 | + * it under the terms of the GNU General Public License version 3 as |
1653 | + * published by the Free Software Foundation. |
1654 | + * |
1655 | + * This program is distributed in the hope that it will be useful, |
1656 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1657 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1658 | + * GNU General Public License for more details. |
1659 | + * |
1660 | + * You should have received a copy of the GNU General Public License |
1661 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1662 | + * |
1663 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
1664 | + */ |
1665 | + |
1666 | +#include "mir/graphics/display.h" |
1667 | + |
1668 | +#include "src/server/input/android/android_input_manager.h" |
1669 | + |
1670 | +#include "mir_toolkit/mir_client_library.h" |
1671 | + |
1672 | +#include "mir_test/fake_shared.h" |
1673 | +#include "mir_test/fake_event_hub_input_configuration.h" |
1674 | +#include "mir_test/fake_event_hub.h" |
1675 | +#include "mir_test/event_factory.h" |
1676 | +#include "mir_test/wait_condition.h" |
1677 | +#include "mir_test_framework/display_server_test_fixture.h" |
1678 | + |
1679 | +#include <gtest/gtest.h> |
1680 | +#include <gmock/gmock.h> |
1681 | + |
1682 | +#include <thread> |
1683 | +#include <functional> |
1684 | + |
1685 | +namespace mi = mir::input; |
1686 | +namespace mia = mi::android; |
1687 | +namespace mis = mi::synthesis; |
1688 | +namespace mt = mir::test; |
1689 | +namespace mtd = mt::doubles; |
1690 | +namespace mtf = mir_test_framework; |
1691 | + |
1692 | +namespace |
1693 | +{ |
1694 | + char const* const mir_test_socket = mtf::test_socket_file().c_str(); |
1695 | +} |
1696 | + |
1697 | +namespace |
1698 | +{ |
1699 | + |
1700 | +struct FocusNotifyingInputManager : public mia::InputManager |
1701 | +{ |
1702 | + FocusNotifyingInputManager(std::shared_ptr<mia::InputConfiguration> const& configuration, |
1703 | + mt::WaitCondition &wait_condition) |
1704 | + : InputManager(configuration), |
1705 | + on_focus_set(wait_condition) |
1706 | + { |
1707 | + |
1708 | + } |
1709 | + |
1710 | + void set_input_focus_to( |
1711 | + std::shared_ptr<mi::SessionTarget> const& session, std::shared_ptr<mi::SurfaceTarget> const& surface) override |
1712 | + { |
1713 | + InputManager::set_input_focus_to(session, surface); |
1714 | + |
1715 | + // We need a synchronization primitive inorder to halt test event injection |
1716 | + // until after a surface has taken focus (lest the events be discarded). |
1717 | + if (surface) |
1718 | + on_focus_set.wake_up_everyone(); |
1719 | + } |
1720 | + |
1721 | + mt::WaitCondition &on_focus_set; |
1722 | +}; |
1723 | + |
1724 | +struct FakeInputServerConfiguration : public mir_test_framework::TestingServerConfiguration |
1725 | +{ |
1726 | + FakeInputServerConfiguration() |
1727 | + : input_config(the_event_filters(), the_display(), std::shared_ptr<mi::CursorListener>()) |
1728 | + { |
1729 | + } |
1730 | + |
1731 | + virtual void inject_input() |
1732 | + { |
1733 | + } |
1734 | + |
1735 | + void exec(mir::DisplayServer* /* display_server */) override |
1736 | + { |
1737 | + input_injection_thread = std::thread([this]() -> void |
1738 | + { |
1739 | + on_focus_set.wait_for_at_most_seconds(10); |
1740 | + fake_event_hub->synthesize_builtin_keyboard_added(); |
1741 | + fake_event_hub->synthesize_device_scan_complete(); |
1742 | + inject_input(); |
1743 | + }); |
1744 | + } |
1745 | + |
1746 | + void on_exit() override |
1747 | + { |
1748 | + input_injection_thread.join(); |
1749 | + } |
1750 | + |
1751 | + std::shared_ptr<mi::InputManager> |
1752 | + the_input_manager() override |
1753 | + { |
1754 | + fake_event_hub = input_config.the_fake_event_hub(); |
1755 | + |
1756 | + return input_manager( |
1757 | + [this]() -> std::shared_ptr<mi::InputManager> |
1758 | + { |
1759 | + return std::make_shared<FocusNotifyingInputManager>(mt::fake_shared(input_config), on_focus_set); |
1760 | + }); |
1761 | + } |
1762 | + |
1763 | + mtd::FakeEventHubInputConfiguration input_config; |
1764 | + mia::FakeEventHub* fake_event_hub; |
1765 | + mt::WaitCondition on_focus_set; |
1766 | + std::thread input_injection_thread; |
1767 | +}; |
1768 | + |
1769 | + |
1770 | +struct ClientConfigCommon : TestingClientConfiguration |
1771 | +{ |
1772 | + ClientConfigCommon() : |
1773 | + connection(0), |
1774 | + surface(0) |
1775 | + { |
1776 | + } |
1777 | + |
1778 | + static void connection_callback(MirConnection* connection, void* context) |
1779 | + { |
1780 | + ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context); |
1781 | + config->connection = connection; |
1782 | + } |
1783 | + |
1784 | + static void create_surface_callback(MirSurface* surface, void* context) |
1785 | + { |
1786 | + ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context); |
1787 | + config->surface_created(surface); |
1788 | + } |
1789 | + |
1790 | + static void release_surface_callback(MirSurface* surface, void* context) |
1791 | + { |
1792 | + ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context); |
1793 | + config->surface_released(surface); |
1794 | + } |
1795 | + |
1796 | + virtual void connected(MirConnection* new_connection) |
1797 | + { |
1798 | + connection = new_connection; |
1799 | + } |
1800 | + |
1801 | + virtual void surface_created(MirSurface* new_surface) |
1802 | + { |
1803 | + surface = new_surface; |
1804 | + } |
1805 | + |
1806 | + virtual void surface_released(MirSurface* /* released_surface */) |
1807 | + { |
1808 | + surface = NULL; |
1809 | + } |
1810 | + |
1811 | + MirConnection* connection; |
1812 | + MirSurface* surface; |
1813 | +}; |
1814 | + |
1815 | +struct MockInputHandler |
1816 | +{ |
1817 | + MOCK_METHOD1(handle_input, void(MirEvent *)); |
1818 | +}; |
1819 | + |
1820 | +struct InputReceivingClient : ClientConfigCommon |
1821 | +{ |
1822 | + InputReceivingClient() |
1823 | + : events_received(0) |
1824 | + { |
1825 | + } |
1826 | + |
1827 | + static void handle_input(MirSurface* /* surface */, MirEvent* ev, void* context) |
1828 | + { |
1829 | + auto client = static_cast<InputReceivingClient *>(context); |
1830 | + client->handler->handle_input(ev); |
1831 | + client->event_received[client->events_received].wake_up_everyone(); |
1832 | + client->events_received++; |
1833 | + } |
1834 | + virtual void expect_input() |
1835 | + { |
1836 | + } |
1837 | + |
1838 | + void exec() |
1839 | + { |
1840 | + handler = std::make_shared<MockInputHandler>(); |
1841 | + |
1842 | + expect_input(); |
1843 | + |
1844 | + mir_wait_for(mir_connect( |
1845 | + mir_test_socket, |
1846 | + __PRETTY_FUNCTION__, |
1847 | + connection_callback, |
1848 | + this)); |
1849 | + ASSERT_TRUE(connection != NULL); |
1850 | + MirSurfaceParameters const request_params = |
1851 | + { |
1852 | + __PRETTY_FUNCTION__, |
1853 | + 640, 480, |
1854 | + mir_pixel_format_abgr_8888, |
1855 | + mir_buffer_usage_hardware |
1856 | + }; |
1857 | + MirEventDelegate const event_delegate = |
1858 | + { |
1859 | + handle_input, |
1860 | + this |
1861 | + }; |
1862 | + mir_wait_for(mir_surface_create(connection, &request_params, &event_delegate, create_surface_callback, this)); |
1863 | + |
1864 | + event_received[0].wait_for_at_most_seconds(5); |
1865 | + event_received[1].wait_for_at_most_seconds(5); |
1866 | + event_received[2].wait_for_at_most_seconds(5); |
1867 | + |
1868 | + mir_surface_release_sync(surface); |
1869 | + |
1870 | + mir_connection_release(connection); |
1871 | + |
1872 | + // ClientConfiguration d'tor is not called on client side so we need this |
1873 | + // in order to not leak the Mock object. |
1874 | + handler.reset(); |
1875 | + } |
1876 | + |
1877 | + std::shared_ptr<MockInputHandler> handler; |
1878 | + mt::WaitCondition event_received[3]; |
1879 | + int events_received; |
1880 | +}; |
1881 | + |
1882 | +} |
1883 | + |
1884 | +using TestClientInput = BespokeDisplayServerTestFixture; |
1885 | + |
1886 | +TEST_F(TestClientInput, clients_receive_key_input) |
1887 | +{ |
1888 | + using namespace ::testing; |
1889 | + |
1890 | + int const num_events_produced = 3; |
1891 | + |
1892 | + struct InputProducingServerConfiguration : FakeInputServerConfiguration |
1893 | + { |
1894 | + void inject_input() |
1895 | + { |
1896 | + // We send multiple events in order to verify the client is handling them |
1897 | + // and server dispatch does not become backed up. |
1898 | + for (int i = 0; i < num_events_produced; i++) |
1899 | + fake_event_hub->synthesize_event(mis::a_key_down_event() |
1900 | + .of_scancode(KEY_ENTER)); |
1901 | + } |
1902 | + } server_config; |
1903 | + launch_server_process(server_config); |
1904 | + |
1905 | + struct KeyReceivingClient : InputReceivingClient |
1906 | + { |
1907 | + void expect_input() |
1908 | + { |
1909 | + using namespace ::testing; |
1910 | + EXPECT_CALL(*handler, handle_input(_)).Times(num_events_produced); |
1911 | + } |
1912 | + } client_config; |
1913 | + launch_client_process(client_config); |
1914 | +} |
1915 | + |
1916 | |
1917 | === modified file 'tests/acceptance-tests/test_client_library.cpp' |
1918 | --- tests/acceptance-tests/test_client_library.cpp 2013-03-22 10:34:16 +0000 |
1919 | +++ tests/acceptance-tests/test_client_library.cpp 2013-04-03 18:49:21 +0000 |
1920 | @@ -164,7 +164,7 @@ |
1921 | mir_buffer_usage_hardware |
1922 | }; |
1923 | |
1924 | - mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this)); |
1925 | + mir_wait_for(mir_surface_create(connection, &request_params, NULL, create_surface_callback, this)); |
1926 | |
1927 | ASSERT_TRUE(surface != NULL); |
1928 | EXPECT_TRUE(mir_surface_is_valid(surface)); |
1929 | @@ -182,7 +182,7 @@ |
1930 | |
1931 | ASSERT_TRUE(surface == NULL); |
1932 | |
1933 | - surface = mir_surface_create_sync(connection, &request_params); |
1934 | + surface = mir_surface_create_sync(connection, &request_params, NULL); |
1935 | |
1936 | ASSERT_TRUE(surface != NULL); |
1937 | EXPECT_TRUE(mir_surface_is_valid(surface)); |
1938 | @@ -226,7 +226,7 @@ |
1939 | mir_buffer_usage_hardware |
1940 | }; |
1941 | |
1942 | - mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this)); |
1943 | + mir_wait_for(mir_surface_create(connection, &request_params, NULL, create_surface_callback, this)); |
1944 | |
1945 | ASSERT_TRUE(surface != NULL); |
1946 | EXPECT_TRUE(mir_surface_is_valid(surface)); |
1947 | @@ -329,7 +329,7 @@ |
1948 | mir_buffer_usage_hardware |
1949 | }; |
1950 | |
1951 | - mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this)); |
1952 | + mir_wait_for(mir_surface_create(connection, &request_params, NULL, create_surface_callback, this)); |
1953 | |
1954 | ASSERT_EQ(old_surface_count + 1, current_surface_count()); |
1955 | } |
1956 | @@ -377,7 +377,7 @@ |
1957 | mir_buffer_usage_hardware |
1958 | }; |
1959 | |
1960 | - mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this)); |
1961 | + mir_wait_for(mir_surface_create(connection, &request_params, NULL, create_surface_callback, this)); |
1962 | ASSERT_TRUE(surface != NULL); |
1963 | |
1964 | buffers = 0; |
1965 | @@ -416,7 +416,7 @@ |
1966 | mir_buffer_usage_software |
1967 | }; |
1968 | |
1969 | - surface = mir_surface_create_sync(connection, &request_params); |
1970 | + surface = mir_surface_create_sync(connection, &request_params, NULL); |
1971 | ASSERT_TRUE(surface != NULL); |
1972 | EXPECT_TRUE(mir_surface_is_valid(surface)); |
1973 | EXPECT_STREQ(mir_surface_get_error_message(surface), ""); |
1974 | @@ -524,7 +524,7 @@ |
1975 | mir_buffer_usage_hardware |
1976 | }; |
1977 | |
1978 | - mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this)); |
1979 | + mir_wait_for(mir_surface_create(connection, &request_params, NULL, create_surface_callback, this)); |
1980 | // TODO surface_create needs to fail safe too. After that is done we should add the following: |
1981 | // TODO mir_wait_for(mir_surface_next_buffer(surface, next_buffer_callback, this)); |
1982 | // TODO mir_wait_for(mir_surface_release( surface, release_surface_callback, this)); |
1983 | |
1984 | === modified file 'tests/acceptance-tests/test_focus_management_api.cpp' |
1985 | --- tests/acceptance-tests/test_focus_management_api.cpp 2013-03-22 10:34:16 +0000 |
1986 | +++ tests/acceptance-tests/test_focus_management_api.cpp 2013-04-03 18:49:21 +0000 |
1987 | @@ -226,7 +226,7 @@ |
1988 | mir_buffer_usage_hardware |
1989 | }; |
1990 | |
1991 | - mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this)); |
1992 | + mir_wait_for(mir_surface_create(connection, &request_params, NULL, create_surface_callback, this)); |
1993 | |
1994 | set_flag(focus_ready); |
1995 | |
1996 | |
1997 | === modified file 'tests/acceptance-tests/test_focus_selection.cpp' |
1998 | --- tests/acceptance-tests/test_focus_selection.cpp 2013-03-29 16:51:35 +0000 |
1999 | +++ tests/acceptance-tests/test_focus_selection.cpp 2013-04-03 18:49:21 +0000 |
2000 | @@ -108,7 +108,7 @@ |
2001 | mir_pixel_format_abgr_8888, |
2002 | mir_buffer_usage_hardware |
2003 | }; |
2004 | - mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this)); |
2005 | + mir_wait_for(mir_surface_create(connection, &request_params, NULL, create_surface_callback, this)); |
2006 | mir_connection_release(connection); |
2007 | } |
2008 | }; |
2009 | |
2010 | === modified file 'tests/acceptance-tests/test_surfaceloop.cpp' |
2011 | --- tests/acceptance-tests/test_surfaceloop.cpp 2013-03-22 10:34:16 +0000 |
2012 | +++ tests/acceptance-tests/test_surfaceloop.cpp 2013-04-03 18:49:21 +0000 |
2013 | @@ -172,13 +172,13 @@ |
2014 | mir_buffer_usage_hardware |
2015 | }; |
2016 | |
2017 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync); |
2018 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync); |
2019 | wait_for_surface_create(ssync); |
2020 | |
2021 | request_params.width = 1600; |
2022 | request_params.height = 1200; |
2023 | |
2024 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync+1); |
2025 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync+1); |
2026 | wait_for_surface_create(ssync+1); |
2027 | |
2028 | MirSurfaceParameters response_params; |
2029 | @@ -225,13 +225,13 @@ |
2030 | mir_buffer_usage_hardware |
2031 | }; |
2032 | |
2033 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync); |
2034 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync); |
2035 | wait_for_surface_create(ssync); |
2036 | |
2037 | request_params.width = 1600; |
2038 | request_params.height = 1200; |
2039 | |
2040 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync+1); |
2041 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync+1); |
2042 | wait_for_surface_create(ssync+1); |
2043 | |
2044 | EXPECT_NE( |
2045 | @@ -270,7 +270,7 @@ |
2046 | }; |
2047 | |
2048 | for (int i = 0; i != max_surface_count; ++i) |
2049 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync+i); |
2050 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync+i); |
2051 | |
2052 | for (int i = 0; i != max_surface_count; ++i) |
2053 | wait_for_surface_create(ssync+i); |
2054 | |
2055 | === modified file 'tests/integration-tests/CMakeLists.txt' |
2056 | --- tests/integration-tests/CMakeLists.txt 2013-03-29 22:30:35 +0000 |
2057 | +++ tests/integration-tests/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
2058 | @@ -12,9 +12,7 @@ |
2059 | add_subdirectory(frontend/) |
2060 | add_subdirectory(shell/) |
2061 | add_subdirectory(process/) |
2062 | -if (NOT MIR_DISABLE_INPUT) |
2063 | add_subdirectory(input/) |
2064 | -endif() |
2065 | |
2066 | if (MIR_PLATFORM STREQUAL "android") |
2067 | include_directories(${PROJECT_SOURCE_DIR}/include/accessory) |
2068 | |
2069 | === modified file 'tests/integration-tests/client/test_client_render.cpp' |
2070 | --- tests/integration-tests/client/test_client_render.cpp 2013-03-29 16:51:35 +0000 |
2071 | +++ tests/integration-tests/client/test_client_render.cpp 2013-04-03 18:49:21 +0000 |
2072 | @@ -102,8 +102,8 @@ |
2073 | surface_parameters.width = test_width; |
2074 | surface_parameters.height = test_height; |
2075 | surface_parameters.pixel_format = mir_pixel_format_abgr_8888; |
2076 | - mir_wait_for(mir_surface_create( connection, &surface_parameters, |
2077 | - &create_callback, &surface)); |
2078 | + mir_wait_for(mir_surface_create(connection, &surface_parameters, |
2079 | + NULL, &create_callback, &surface)); |
2080 | |
2081 | auto graphics_region = std::make_shared<MirGraphicsRegion>(); |
2082 | /* grab a buffer*/ |
2083 | @@ -143,8 +143,8 @@ |
2084 | surface_parameters.height = test_height; |
2085 | surface_parameters.pixel_format = mir_pixel_format_abgr_8888; |
2086 | |
2087 | - mir_wait_for(mir_surface_create( connection, &surface_parameters, |
2088 | - &create_callback, &surface)); |
2089 | + mir_wait_for(mir_surface_create(connection, &surface_parameters, |
2090 | + NULL, &create_callback, &surface)); |
2091 | |
2092 | auto graphics_region = std::make_shared<MirGraphicsRegion>(); |
2093 | mir_surface_get_graphics_region( surface, graphics_region.get()); |
2094 | @@ -187,8 +187,8 @@ |
2095 | surface_parameters.height = test_height; |
2096 | surface_parameters.pixel_format = mir_pixel_format_abgr_8888; |
2097 | |
2098 | - mir_wait_for(mir_surface_create( connection, &surface_parameters, |
2099 | - &create_callback, &surface)); |
2100 | + mir_wait_for(mir_surface_create(connection, &surface_parameters, |
2101 | + NULL, &create_callback, &surface)); |
2102 | |
2103 | int major, minor, n; |
2104 | EGLDisplay disp; |
2105 | @@ -249,8 +249,8 @@ |
2106 | surface_parameters.height = test_height; |
2107 | surface_parameters.pixel_format = mir_pixel_format_abgr_8888; |
2108 | |
2109 | - mir_wait_for(mir_surface_create( connection, &surface_parameters, |
2110 | - &create_callback, &surface)); |
2111 | + mir_wait_for(mir_surface_create(connection, &surface_parameters, |
2112 | + NULL, &create_callback, &surface)); |
2113 | |
2114 | int major, minor, n; |
2115 | EGLDisplay disp; |
2116 | |
2117 | === modified file 'tests/integration-tests/input/android/test_android_cursor_listener.cpp' |
2118 | --- tests/integration-tests/input/android/test_android_cursor_listener.cpp 2013-03-13 08:09:52 +0000 |
2119 | +++ tests/integration-tests/input/android/test_android_cursor_listener.cpp 2013-04-03 18:49:21 +0000 |
2120 | @@ -44,7 +44,6 @@ |
2121 | namespace mtd = mir::test::doubles; |
2122 | |
2123 | using mtd::MockEventFilter; |
2124 | -using mir::WaitCondition; |
2125 | |
2126 | namespace |
2127 | { |
2128 | @@ -100,7 +99,7 @@ |
2129 | { |
2130 | using namespace ::testing; |
2131 | |
2132 | - auto wait_condition = std::make_shared<WaitCondition>(); |
2133 | + auto wait_condition = std::make_shared<mt::WaitCondition>(); |
2134 | |
2135 | static const float x = 100.f; |
2136 | static const float y = 100.f; |
2137 | @@ -109,7 +108,7 @@ |
2138 | |
2139 | // The stack doesn't like shutting down while events are still moving through |
2140 | EXPECT_CALL(event_filter, handles(_)) |
2141 | - .WillOnce(ReturnFalseAndWakeUp(wait_condition)); |
2142 | + .WillOnce(mt::ReturnFalseAndWakeUp(wait_condition)); |
2143 | |
2144 | fake_event_hub->synthesize_builtin_cursor_added(); |
2145 | fake_event_hub->synthesize_device_scan_complete(); |
2146 | |
2147 | === modified file 'tests/integration-tests/input/android/test_android_input_manager.cpp' |
2148 | --- tests/integration-tests/input/android/test_android_input_manager.cpp 2013-04-02 16:40:08 +0000 |
2149 | +++ tests/integration-tests/input/android/test_android_input_manager.cpp 2013-04-03 18:49:21 +0000 |
2150 | @@ -53,7 +53,6 @@ |
2151 | namespace mtd = mir::test::doubles; |
2152 | |
2153 | using mtd::MockEventFilter; |
2154 | -using mir::WaitCondition; |
2155 | |
2156 | namespace |
2157 | { |
2158 | @@ -100,13 +99,13 @@ |
2159 | { |
2160 | using namespace ::testing; |
2161 | |
2162 | - WaitCondition wait_condition; |
2163 | + mt::WaitCondition wait_condition; |
2164 | |
2165 | EXPECT_CALL( |
2166 | event_filter, |
2167 | handles(mt::KeyDownEvent())) |
2168 | .Times(1) |
2169 | - .WillOnce(ReturnFalseAndWakeUp(&wait_condition)); |
2170 | + .WillOnce(mt::ReturnFalseAndWakeUp(&wait_condition)); |
2171 | |
2172 | fake_event_hub->synthesize_builtin_keyboard_added(); |
2173 | fake_event_hub->synthesize_device_scan_complete(); |
2174 | @@ -121,13 +120,13 @@ |
2175 | { |
2176 | using namespace ::testing; |
2177 | |
2178 | - WaitCondition wait_condition; |
2179 | + mt::WaitCondition wait_condition; |
2180 | |
2181 | EXPECT_CALL( |
2182 | event_filter, |
2183 | handles(mt::ButtonDownEvent())) |
2184 | .Times(1) |
2185 | - .WillOnce(ReturnFalseAndWakeUp(&wait_condition)); |
2186 | + .WillOnce(mt::ReturnFalseAndWakeUp(&wait_condition)); |
2187 | |
2188 | fake_event_hub->synthesize_builtin_cursor_added(); |
2189 | fake_event_hub->synthesize_device_scan_complete(); |
2190 | @@ -141,7 +140,7 @@ |
2191 | { |
2192 | using namespace ::testing; |
2193 | |
2194 | - WaitCondition wait_condition; |
2195 | + mt::WaitCondition wait_condition; |
2196 | |
2197 | // We get absolute motion events since we have a pointer controller. |
2198 | { |
2199 | @@ -152,7 +151,7 @@ |
2200 | .WillOnce(Return(false)); |
2201 | EXPECT_CALL(event_filter, |
2202 | handles(mt::MotionEvent(200, 100))) |
2203 | - .WillOnce(ReturnFalseAndWakeUp(&wait_condition)); |
2204 | + .WillOnce(mt::ReturnFalseAndWakeUp(&wait_condition)); |
2205 | } |
2206 | |
2207 | fake_event_hub->synthesize_builtin_cursor_added(); |
2208 | @@ -253,7 +252,7 @@ |
2209 | { |
2210 | using namespace ::testing; |
2211 | |
2212 | - WaitCondition wait_condition; |
2213 | + mt::WaitCondition wait_condition; |
2214 | |
2215 | mtd::StubSessionTarget session; |
2216 | mtd::StubSurfaceTarget surface(test_input_fd); |
2217 | @@ -261,7 +260,7 @@ |
2218 | EXPECT_CALL(event_filter, handles(_)).Times(1).WillOnce(Return(false)); |
2219 | // We return -1 here to skip publishing of the event (to an unconnected test socket!). |
2220 | EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(test_input_fd), _, _)) |
2221 | - .Times(1).WillOnce(DoAll(WakeUp(&wait_condition), Return(-1))); |
2222 | + .Times(1).WillOnce(DoAll(mt::WakeUp(&wait_condition), Return(-1))); |
2223 | |
2224 | input_manager->set_input_focus_to(mt::fake_shared(session), mt::fake_shared(surface)); |
2225 | |
2226 | |
2227 | === modified file 'tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp' |
2228 | --- tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 2013-04-02 16:40:08 +0000 |
2229 | +++ tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 2013-04-03 18:49:21 +0000 |
2230 | @@ -95,16 +95,15 @@ |
2231 | } |
2232 | |
2233 | using mir::FakeEventHubSetup; |
2234 | -using mir::WaitCondition; |
2235 | |
2236 | TEST_F(FakeEventHubSetup, fake_event_hub_dispatches_to_filter) |
2237 | { |
2238 | using namespace ::testing; |
2239 | |
2240 | - mir::WaitCondition wait_condition; |
2241 | + mt::WaitCondition wait_condition; |
2242 | |
2243 | EXPECT_CALL(event_filter, handles(mt::KeyDownEvent())).Times(1) |
2244 | - .WillOnce(ReturnFalseAndWakeUp(&wait_condition)); |
2245 | + .WillOnce(mt::ReturnFalseAndWakeUp(&wait_condition)); |
2246 | |
2247 | event_hub->synthesize_builtin_keyboard_added(); |
2248 | event_hub->synthesize_device_scan_complete(); |
2249 | |
2250 | === modified file 'tests/integration-tests/test_error_reporting.cpp' |
2251 | --- tests/integration-tests/test_error_reporting.cpp 2013-03-22 10:34:16 +0000 |
2252 | +++ tests/integration-tests/test_error_reporting.cpp 2013-04-03 18:49:21 +0000 |
2253 | @@ -238,7 +238,7 @@ |
2254 | mir_buffer_usage_hardware |
2255 | }; |
2256 | |
2257 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync); |
2258 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync); |
2259 | |
2260 | wait_for_surface_create(ssync); |
2261 | |
2262 | |
2263 | === modified file 'tests/integration-tests/test_surfaceloop.cpp' |
2264 | --- tests/integration-tests/test_surfaceloop.cpp 2013-03-25 10:18:17 +0000 |
2265 | +++ tests/integration-tests/test_surfaceloop.cpp 2013-04-03 18:49:21 +0000 |
2266 | @@ -286,7 +286,7 @@ |
2267 | mir_buffer_usage_hardware |
2268 | }; |
2269 | |
2270 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync); |
2271 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync); |
2272 | |
2273 | wait_for_surface_create(ssync); |
2274 | |
2275 | @@ -388,7 +388,7 @@ |
2276 | mir_pixel_format_abgr_8888, |
2277 | mir_buffer_usage_hardware |
2278 | }; |
2279 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync); |
2280 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync); |
2281 | |
2282 | wait_for_surface_create(ssync); |
2283 | |
2284 | @@ -522,7 +522,7 @@ |
2285 | }; |
2286 | |
2287 | for (int i = 0; i != max_surface_count; ++i) |
2288 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync+i); |
2289 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync+i); |
2290 | |
2291 | for (int i = 0; i != max_surface_count; ++i) |
2292 | wait_for_surface_create(ssync+i); |
2293 | @@ -571,7 +571,7 @@ |
2294 | }; |
2295 | |
2296 | for (int i = 0; i != max_surface_count; ++i) |
2297 | - mir_surface_create(connection, &request_params, create_surface_callback, ssync+i); |
2298 | + mir_surface_create(connection, &request_params, NULL, create_surface_callback, ssync+i); |
2299 | |
2300 | for (int i = 0; i != max_surface_count; ++i) |
2301 | wait_for_surface_create(ssync+i); |
2302 | |
2303 | === modified file 'tests/mir_test_doubles/CMakeLists.txt' |
2304 | --- tests/mir_test_doubles/CMakeLists.txt 2013-03-28 09:50:09 +0000 |
2305 | +++ tests/mir_test_doubles/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
2306 | @@ -10,12 +10,10 @@ |
2307 | event_factory.cpp |
2308 | ) |
2309 | |
2310 | -if (NOT MIR_DISABLE_INPUT) |
2311 | list(APPEND TEST_UTILS_SRCS |
2312 | fake_event_hub.cpp |
2313 | fake_event_hub_input_configuration.cpp |
2314 | ) |
2315 | -endif() |
2316 | |
2317 | list(APPEND TEST_UTILS_SRCS |
2318 | test_protobuf_socket_server.cpp |
2319 | |
2320 | === modified file 'tests/unit-tests/CMakeLists.txt' |
2321 | --- tests/unit-tests/CMakeLists.txt 2013-03-29 22:30:35 +0000 |
2322 | +++ tests/unit-tests/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
2323 | @@ -11,11 +11,8 @@ |
2324 | add_subdirectory(shell/) |
2325 | add_subdirectory(geometry/) |
2326 | add_subdirectory(graphics/) |
2327 | -#TODO stubbed out to run tests on emulator |
2328 | -if (NOT MIR_DISABLE_INPUT) |
2329 | add_subdirectory(input/) |
2330 | add_subdirectory(android_input/) |
2331 | -endif() |
2332 | add_subdirectory(surfaces/) |
2333 | add_subdirectory(draw/) |
2334 | |
2335 | |
2336 | === modified file 'tests/unit-tests/client/CMakeLists.txt' |
2337 | --- tests/unit-tests/client/CMakeLists.txt 2013-03-24 23:33:49 +0000 |
2338 | +++ tests/unit-tests/client/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
2339 | @@ -16,4 +16,8 @@ |
2340 | add_subdirectory("gbm") |
2341 | endif() |
2342 | |
2343 | +if (NOT MIR_DISABLE_INPUT) |
2344 | +add_subdirectory("input") |
2345 | +endif() |
2346 | + |
2347 | set(UNIT_TEST_SOURCES ${UNIT_TEST_SOURCES} PARENT_SCOPE) |
2348 | |
2349 | === added directory 'tests/unit-tests/client/input' |
2350 | === added file 'tests/unit-tests/client/input/CMakeLists.txt' |
2351 | --- tests/unit-tests/client/input/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
2352 | +++ tests/unit-tests/client/input/CMakeLists.txt 2013-04-03 18:49:21 +0000 |
2353 | @@ -0,0 +1,9 @@ |
2354 | +list(APPEND UNIT_TEST_SOURCES |
2355 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_receiver_thread.cpp |
2356 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_receiver.cpp |
2357 | +) |
2358 | + |
2359 | +set( |
2360 | + UNIT_TEST_SOURCES |
2361 | + ${UNIT_TEST_SOURCES} |
2362 | + PARENT_SCOPE) |
2363 | |
2364 | === added file 'tests/unit-tests/client/input/test_android_input_receiver.cpp' |
2365 | --- tests/unit-tests/client/input/test_android_input_receiver.cpp 1970-01-01 00:00:00 +0000 |
2366 | +++ tests/unit-tests/client/input/test_android_input_receiver.cpp 2013-04-03 18:49:21 +0000 |
2367 | @@ -0,0 +1,198 @@ |
2368 | +/* |
2369 | + * Copyright © 2013 Canonical Ltd. |
2370 | + * |
2371 | + * This program is free software: you can redistribute it and/or modify |
2372 | + * it under the terms of the GNU General Public License version 3 as |
2373 | + * published by the Free Software Foundation. |
2374 | + * |
2375 | + * This program is distributed in the hope that it will be useful, |
2376 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2377 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2378 | + * GNU General Public License for more details. |
2379 | + * |
2380 | + * You should have received a copy of the GNU General Public License |
2381 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2382 | + * |
2383 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
2384 | + */ |
2385 | + |
2386 | +#include "src/client/input/android_input_receiver.h" |
2387 | +#include "mir_toolkit/input/event.h" |
2388 | + |
2389 | +#include <androidfw/InputTransport.h> |
2390 | + |
2391 | +#include <gmock/gmock.h> |
2392 | +#include <gtest/gtest.h> |
2393 | + |
2394 | +#include <unistd.h> |
2395 | +#include <memory> |
2396 | + |
2397 | +namespace mclia = mir::client::input::android; |
2398 | + |
2399 | +namespace droidinput = android; |
2400 | + |
2401 | +namespace |
2402 | +{ |
2403 | + |
2404 | +class TestingInputProducer |
2405 | +{ |
2406 | +public: |
2407 | + TestingInputProducer(droidinput::sp<droidinput::InputChannel> input_channel) : |
2408 | + input_publisher(std::make_shared<droidinput::InputPublisher>(input_channel)), |
2409 | + incrementing_seq_id(1), // Sequence id must be > 0 or publisher will reject |
2410 | + testing_key_event_key_code(13) |
2411 | + { |
2412 | + } |
2413 | + |
2414 | + // The input publisher does not care about event semantics so we only highlight |
2415 | + // a few fields for transport verification |
2416 | + void produce_a_key_event() |
2417 | + { |
2418 | + input_publisher->publishKeyEvent( |
2419 | + incrementing_seq_id, |
2420 | + filler_device_id, |
2421 | + 0 /* source */, |
2422 | + 0 /* action */, |
2423 | + 0 /* flags */, |
2424 | + testing_key_event_key_code, |
2425 | + 0 /* scan_code */, |
2426 | + 0 /* meta_state */, |
2427 | + 0 /* repeat_count */, |
2428 | + 0 /* down_time */, |
2429 | + 0 /* event_time */); |
2430 | + } |
2431 | + void produce_a_motion_event() |
2432 | + { |
2433 | + droidinput::PointerProperties filler_pointer_properties; |
2434 | + droidinput::PointerCoords filler_pointer_coordinates; |
2435 | + |
2436 | + memset(&filler_pointer_properties, 0, sizeof(droidinput::PointerProperties)); |
2437 | + memset(&filler_pointer_coordinates, 0, sizeof(droidinput::PointerCoords)); |
2438 | + |
2439 | + input_publisher->publishMotionEvent( |
2440 | + incrementing_seq_id, |
2441 | + filler_device_id, |
2442 | + 0 /* source */, |
2443 | + motion_event_action_flags, |
2444 | + 0 /* flags */, |
2445 | + 0 /* edge_flags */, |
2446 | + 0 /* meta_state */, |
2447 | + 0 /* button_state */, |
2448 | + 0 /* x_offset */, 0 /* y_offset */, |
2449 | + 0 /* x_precision */, 0 /* y_precision */, |
2450 | + 0 /* down_time */, |
2451 | + 0 /* event_time */, |
2452 | + default_pointer_count, |
2453 | + &filler_pointer_properties, |
2454 | + &filler_pointer_coordinates); |
2455 | + } |
2456 | + |
2457 | + bool must_receive_handled_signal() |
2458 | + { |
2459 | + uint32_t seq; |
2460 | + bool handled; |
2461 | + |
2462 | + auto status = input_publisher->receiveFinishedSignal(&seq, &handled); |
2463 | + return (status == droidinput::OK) && handled; |
2464 | + } |
2465 | + |
2466 | + std::shared_ptr<droidinput::InputPublisher> input_publisher; |
2467 | + |
2468 | + int incrementing_seq_id; |
2469 | + int32_t testing_key_event_key_code; |
2470 | + |
2471 | + // Some default values |
2472 | + // device_id must be > 0 or input publisher will reject |
2473 | + static const int32_t filler_device_id = 1; |
2474 | + // AMOTION_EVENT_ACTION_MOVE is necessary to engage batching behavior |
2475 | + static const int32_t motion_event_action_flags = AMOTION_EVENT_ACTION_MOVE; |
2476 | + // We have to have at least 1 pointer or the publisher will fail to marshal a motion event |
2477 | + static const int32_t default_pointer_count = 1; |
2478 | +}; |
2479 | + |
2480 | +class AndroidInputReceiverSetup : public testing::Test |
2481 | +{ |
2482 | +public: |
2483 | + AndroidInputReceiverSetup() |
2484 | + { |
2485 | + droidinput::String8 const testing_channel_name = droidinput::String8("Terrapin"); |
2486 | + auto status = droidinput::InputChannel::openInputChannelPair(testing_channel_name, |
2487 | + android_client_channel, |
2488 | + android_server_channel); |
2489 | + |
2490 | + EXPECT_EQ(droidinput::OK, status); |
2491 | + } |
2492 | + |
2493 | + void flush_channels() |
2494 | + { |
2495 | + fsync(android_server_channel->getFd()); |
2496 | + fsync(android_client_channel->getFd()); |
2497 | + } |
2498 | + |
2499 | + droidinput::sp<droidinput::InputChannel> android_client_channel; |
2500 | + droidinput::sp<droidinput::InputChannel> android_server_channel; |
2501 | + |
2502 | + static std::chrono::milliseconds const next_event_timeout; |
2503 | +}; |
2504 | + |
2505 | +std::chrono::milliseconds const AndroidInputReceiverSetup::next_event_timeout(1000); |
2506 | + |
2507 | +} |
2508 | + |
2509 | +TEST_F(AndroidInputReceiverSetup, receiever_takes_channel_fd) |
2510 | +{ |
2511 | + mclia::InputReceiver receiver(android_client_channel); |
2512 | + |
2513 | + EXPECT_EQ(android_client_channel->getFd(), receiver.fd()); |
2514 | +} |
2515 | + |
2516 | +TEST_F(AndroidInputReceiverSetup, receiver_receives_key_events) |
2517 | +{ |
2518 | + mclia::InputReceiver receiver(android_client_channel); |
2519 | + TestingInputProducer producer(android_server_channel); |
2520 | + |
2521 | + producer.produce_a_key_event(); |
2522 | + |
2523 | + flush_channels(); |
2524 | + |
2525 | + MirEvent ev; |
2526 | + EXPECT_EQ(true, receiver.next_event(next_event_timeout, ev)); |
2527 | + EXPECT_EQ(MIR_INPUT_EVENT_TYPE_KEY, ev.type); |
2528 | + EXPECT_EQ(producer.testing_key_event_key_code, ev.details.key.key_code); |
2529 | +} |
2530 | + |
2531 | +TEST_F(AndroidInputReceiverSetup, receiver_handles_events) |
2532 | +{ |
2533 | + mclia::InputReceiver receiver(android_client_channel); |
2534 | + TestingInputProducer producer(android_server_channel); |
2535 | + |
2536 | + producer.produce_a_key_event(); |
2537 | + flush_channels(); |
2538 | + |
2539 | + MirEvent ev; |
2540 | + EXPECT_EQ(true, receiver.next_event(next_event_timeout, ev)); |
2541 | + |
2542 | + flush_channels(); |
2543 | + |
2544 | + EXPECT_TRUE (producer.must_receive_handled_signal()); |
2545 | +} |
2546 | + |
2547 | +TEST_F(AndroidInputReceiverSetup, receiver_consumes_batched_motion_events) |
2548 | +{ |
2549 | + mclia::InputReceiver receiver(android_client_channel); |
2550 | + TestingInputProducer producer(android_server_channel); |
2551 | + |
2552 | + // Produce 3 motion events before client handles any. |
2553 | + producer.produce_a_motion_event(); |
2554 | + producer.produce_a_motion_event(); |
2555 | + producer.produce_a_motion_event(); |
2556 | + |
2557 | + flush_channels(); |
2558 | + |
2559 | + MirEvent ev; |
2560 | + // Handle all three events as a batched event |
2561 | + EXPECT_TRUE(receiver.next_event(next_event_timeout, ev)); |
2562 | + // Now there should be no events |
2563 | + EXPECT_FALSE(receiver.next_event(std::chrono::milliseconds(1), ev)); // Minimal timeout needed for valgrind |
2564 | +} |
2565 | + |
2566 | |
2567 | === added file 'tests/unit-tests/client/input/test_android_input_receiver_thread.cpp' |
2568 | --- tests/unit-tests/client/input/test_android_input_receiver_thread.cpp 1970-01-01 00:00:00 +0000 |
2569 | +++ tests/unit-tests/client/input/test_android_input_receiver_thread.cpp 2013-04-03 18:49:21 +0000 |
2570 | @@ -0,0 +1,152 @@ |
2571 | +/* |
2572 | + * Copyright © 2013 Canonical Ltd. |
2573 | + * |
2574 | + * This program is free software: you can redistribute it and/or modify it |
2575 | + * under the terms of the GNU Lesser General Public License version 3, |
2576 | + * as published by the Free Software Foundation. |
2577 | + * |
2578 | + * This program is distributed in the hope that it will be useful, |
2579 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2580 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2581 | + * GNU General Public License for more details. |
2582 | + * |
2583 | + * You should have received a copy of the GNU Lesser General Public License |
2584 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2585 | + * |
2586 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
2587 | + */ |
2588 | + |
2589 | +#include "src/client/input/android_input_receiver_thread.h" |
2590 | +#include "src/client/input/android_input_receiver.h" |
2591 | + |
2592 | +#include "mir_toolkit/mir_client_library.h" |
2593 | + |
2594 | +#include <gtest/gtest.h> |
2595 | +#include <gmock/gmock.h> |
2596 | + |
2597 | +#include <androidfw/InputTransport.h> |
2598 | + |
2599 | +#include <atomic> |
2600 | + |
2601 | +#include <fcntl.h> |
2602 | + |
2603 | +namespace mclia = mir::client::input::android; |
2604 | + |
2605 | +namespace |
2606 | +{ |
2607 | + |
2608 | +struct MockEventHandler |
2609 | +{ |
2610 | + MOCK_METHOD1(handle_event, void(MirEvent*)); |
2611 | +}; |
2612 | + |
2613 | +struct MockInputReceiver : public mclia::InputReceiver |
2614 | +{ |
2615 | + MockInputReceiver(int fd) |
2616 | + : InputReceiver(fd) |
2617 | + { |
2618 | + } |
2619 | + MOCK_METHOD1(next_event, bool(MirEvent &)); |
2620 | +}; |
2621 | + |
2622 | +struct AndroidInputReceiverThreadSetup : public testing::Test |
2623 | +{ |
2624 | + AndroidInputReceiverThreadSetup() |
2625 | + { |
2626 | + test_receiver_fd = open("/dev/null", O_APPEND); |
2627 | + input_receiver = std::make_shared<MockInputReceiver>(test_receiver_fd); |
2628 | + } |
2629 | + virtual ~AndroidInputReceiverThreadSetup() |
2630 | + { |
2631 | + close(test_receiver_fd); |
2632 | + } |
2633 | + |
2634 | + int test_receiver_fd; |
2635 | + std::shared_ptr<MockInputReceiver> input_receiver; |
2636 | +}; |
2637 | + |
2638 | +ACTION_P(StopThread, thread) |
2639 | +{ |
2640 | + thread->stop(); |
2641 | +// thread->join(); |
2642 | +} |
2643 | + |
2644 | +} |
2645 | + |
2646 | +TEST_F(AndroidInputReceiverThreadSetup, reads_events_until_stopped) |
2647 | +{ |
2648 | + using namespace ::testing; |
2649 | + |
2650 | + mclia::InputReceiverThread input_thread(input_receiver, |
2651 | + std::function<void(MirEvent*)>()); |
2652 | + { |
2653 | + InSequence seq; |
2654 | + EXPECT_CALL(*input_receiver, next_event(_)).Times(1).WillOnce(Return(false)); |
2655 | + EXPECT_CALL(*input_receiver, next_event(_)).Times(1).WillOnce(Return(false)); |
2656 | + EXPECT_CALL(*input_receiver, next_event(_)).Times(1).WillOnce(DoAll(StopThread(&input_thread), Return(false))); |
2657 | + } |
2658 | + input_thread.start(); |
2659 | + input_thread.join(); |
2660 | +} |
2661 | + |
2662 | +TEST_F(AndroidInputReceiverThreadSetup, receives_and_dispatches_available_events_when_ready) |
2663 | +{ |
2664 | + using namespace ::testing; |
2665 | + MockEventHandler mock_handler; |
2666 | + |
2667 | + struct InputDelegate |
2668 | + { |
2669 | + InputDelegate(MockEventHandler& handler) |
2670 | + : handler(handler) {} |
2671 | + void operator()(MirEvent* ev) |
2672 | + { |
2673 | + handler.handle_event(ev); |
2674 | + } |
2675 | + MockEventHandler &handler; |
2676 | + } input_delegate(mock_handler); |
2677 | + |
2678 | + mclia::InputReceiverThread input_thread(input_receiver, input_delegate); |
2679 | + { |
2680 | + InSequence seq; |
2681 | + |
2682 | + EXPECT_CALL(*input_receiver, next_event(_)).Times(1).WillOnce(Return(true)); |
2683 | + EXPECT_CALL(*input_receiver, next_event(_)).Times(1).WillOnce(Return(false)); |
2684 | + EXPECT_CALL(*input_receiver, next_event(_)).Times(1).WillOnce(DoAll(StopThread(&input_thread), Return(true))); |
2685 | + } |
2686 | + EXPECT_CALL(mock_handler, handle_event(_)).Times(2); |
2687 | + |
2688 | + input_thread.start(); |
2689 | + input_thread.join(); |
2690 | +} |
2691 | + |
2692 | +TEST_F(AndroidInputReceiverThreadSetup, input_callback_invoked_from_thread) |
2693 | +{ |
2694 | + using namespace ::testing; |
2695 | + MockEventHandler mock_handler; |
2696 | + std::atomic<bool> handled; |
2697 | + |
2698 | + handled = false; |
2699 | + |
2700 | + struct InputDelegate |
2701 | + { |
2702 | + InputDelegate(std::atomic<bool> &handled) |
2703 | + : handled(handled) {} |
2704 | + void operator()(MirEvent* /*ev*/) |
2705 | + { |
2706 | + handled = true; |
2707 | + } |
2708 | + std::atomic<bool> &handled; |
2709 | + } input_delegate(handled); |
2710 | + |
2711 | + mclia::InputReceiverThread input_thread(input_receiver, input_delegate); |
2712 | + { |
2713 | + InSequence seq; |
2714 | + |
2715 | + EXPECT_CALL(*input_receiver, next_event(_)).Times(1).WillOnce(DoAll(StopThread(&input_thread), Return(true))); |
2716 | + } |
2717 | + |
2718 | + input_thread.start(); |
2719 | + while (handled == false) { } // We would block forever here were delivery not threaded |
2720 | + input_thread.join(); |
2721 | +} |
2722 | + |
2723 | |
2724 | === modified file 'tests/unit-tests/client/test_client_mir_surface.cpp' |
2725 | --- tests/unit-tests/client/test_client_mir_surface.cpp 2013-03-26 09:37:47 +0000 |
2726 | +++ tests/unit-tests/client/test_client_mir_surface.cpp 2013-04-03 18:49:21 +0000 |
2727 | @@ -20,25 +20,30 @@ |
2728 | #include "mir_toolkit/mir_client_library.h" |
2729 | #include "src/client/mir_logger.h" |
2730 | #include "src/client/client_buffer.h" |
2731 | -#include "src/client/client_buffer_depository.h" |
2732 | #include "src/client/client_buffer_factory.h" |
2733 | #include "src/client/client_platform.h" |
2734 | #include "src/client/client_platform_factory.h" |
2735 | #include "src/client/mir_surface.h" |
2736 | #include "src/client/mir_connection.h" |
2737 | +#include "src/client/input/input_platform.h" |
2738 | +#include "src/client/input/input_receiver_thread.h" |
2739 | #include "mir/frontend/resource_cache.h" |
2740 | |
2741 | #include "mir_test/test_protobuf_server.h" |
2742 | #include "mir_test/stub_server_tool.h" |
2743 | #include "mir_test/test_protobuf_client.h" |
2744 | #include "mir_test/gmock_fixes.h" |
2745 | +#include "mir_test/fake_shared.h" |
2746 | |
2747 | #include <cstring> |
2748 | |
2749 | #include <gtest/gtest.h> |
2750 | #include <gmock/gmock.h> |
2751 | |
2752 | +#include <fcntl.h> |
2753 | + |
2754 | namespace mcl = mir::client; |
2755 | +namespace mcli = mcl::input; |
2756 | namespace mp = mir::protobuf; |
2757 | namespace geom = mir::geometry; |
2758 | |
2759 | @@ -52,10 +57,17 @@ |
2760 | MockServerPackageGenerator() |
2761 | : global_buffer_id(0) |
2762 | { |
2763 | - generate_unique_buffer(); |
2764 | width_sent = 891; |
2765 | height_sent = 458; |
2766 | pf_sent = mir_pixel_format_abgr_8888; |
2767 | + |
2768 | + input_fd = open("/dev/null", O_APPEND); |
2769 | + } |
2770 | + ~MockServerPackageGenerator() |
2771 | + { |
2772 | + close(input_fd); |
2773 | + for (int i = 0; i < server_package.fd_items; i++) |
2774 | + close(server_package.fd[0]); |
2775 | } |
2776 | |
2777 | void create_surface(google::protobuf::RpcController*, |
2778 | @@ -86,8 +98,12 @@ |
2779 | int num_fd = 2, num_data = 8; |
2780 | for (auto i=0; i<num_fd; i++) |
2781 | { |
2782 | - server_package.fd[i] = global_buffer_id * i; |
2783 | + if (server_package.fd[i]) |
2784 | + close(server_package.fd[i]); |
2785 | + server_package.fd[i] = open("/dev/null", O_APPEND); |
2786 | } |
2787 | + server_package.fd_items = num_fd; |
2788 | + server_package.data_items = num_data; |
2789 | for (auto i=0; i<num_data; i++) |
2790 | { |
2791 | server_package.data[i] = (global_buffer_id + i) * 2; |
2792 | @@ -100,16 +116,20 @@ |
2793 | int width_sent; |
2794 | int height_sent; |
2795 | int pf_sent; |
2796 | + |
2797 | + int input_fd; |
2798 | |
2799 | private: |
2800 | int global_buffer_id; |
2801 | |
2802 | void create_buffer_response(mir::protobuf::Buffer* response) |
2803 | { |
2804 | + generate_unique_buffer(); |
2805 | + |
2806 | response->set_buffer_id(global_buffer_id); |
2807 | |
2808 | /* assemble buffers */ |
2809 | - response->set_fds_on_side_channel(1); |
2810 | + response->set_fds_on_side_channel(server_package.fd_items); |
2811 | for (int i=0; i< server_package.data_items; i++) |
2812 | { |
2813 | response->add_data(server_package.data[i]); |
2814 | @@ -120,16 +140,18 @@ |
2815 | } |
2816 | |
2817 | response->set_stride(server_package.stride); |
2818 | - |
2819 | - generate_unique_buffer(); |
2820 | } |
2821 | |
2822 | void create_surface_response(mir::protobuf::Surface* response) |
2823 | { |
2824 | + response->set_fds_on_side_channel(1); |
2825 | + |
2826 | response->mutable_id()->set_value(2); |
2827 | response->set_width(width_sent); |
2828 | response->set_height(height_sent); |
2829 | response->set_pixel_format(pf_sent); |
2830 | + response->add_fd(input_fd); |
2831 | + |
2832 | create_buffer_response(response->mutable_buffer()); |
2833 | } |
2834 | }; |
2835 | @@ -207,6 +229,26 @@ |
2836 | } |
2837 | }; |
2838 | |
2839 | +struct StubClientInputPlatform : public mcli::InputPlatform |
2840 | +{ |
2841 | + std::shared_ptr<mcli::InputReceiverThread> create_input_thread(int /* fd */, std::function<void(MirEvent*)> const& /* callback */) |
2842 | + { |
2843 | + return std::shared_ptr<mcli::InputReceiverThread>(); |
2844 | + } |
2845 | +}; |
2846 | + |
2847 | +struct MockClientInputPlatform : public mcli::InputPlatform |
2848 | +{ |
2849 | + MOCK_METHOD2(create_input_thread, std::shared_ptr<mcli::InputReceiverThread>(int, std::function<void(MirEvent*)> const&)); |
2850 | +}; |
2851 | + |
2852 | +struct MockInputReceiverThread : public mcli::InputReceiverThread |
2853 | +{ |
2854 | + MOCK_METHOD0(start, void()); |
2855 | + MOCK_METHOD0(stop, void()); |
2856 | + MOCK_METHOD0(join, void()); |
2857 | +}; |
2858 | + |
2859 | } |
2860 | } |
2861 | |
2862 | @@ -232,6 +274,8 @@ |
2863 | |
2864 | mock_buffer_factory = std::make_shared<mt::MockClientBufferFactory>(); |
2865 | |
2866 | + input_platform = std::make_shared<mt::StubClientInputPlatform>(); |
2867 | + |
2868 | params = MirSurfaceParameters{"test", 33, 45, mir_pixel_format_abgr_8888, |
2869 | mir_buffer_usage_hardware}; |
2870 | |
2871 | @@ -261,6 +305,7 @@ |
2872 | |
2873 | MirSurfaceParameters params; |
2874 | std::shared_ptr<mt::MockClientBufferFactory> mock_buffer_factory; |
2875 | + std::shared_ptr<mt::StubClientInputPlatform> input_platform; |
2876 | |
2877 | mir::protobuf::Connection response; |
2878 | mir::protobuf::ConnectParameters connect_parameters; |
2879 | @@ -282,13 +327,7 @@ |
2880 | EXPECT_CALL(*mock_buffer_factory, create_buffer(_,_,_)) |
2881 | .Times(1); |
2882 | |
2883 | - auto surface = std::make_shared<MirSurface> (connection.get(), |
2884 | - *client_comm_channel, |
2885 | - logger, |
2886 | - mock_buffer_factory, |
2887 | - params, |
2888 | - &empty_callback, |
2889 | - nullptr); |
2890 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, mock_buffer_factory, input_platform, params, nullptr, &empty_callback, nullptr); |
2891 | |
2892 | auto wait_handle = surface->get_create_wait_handle(); |
2893 | wait_handle->wait_for_result(); |
2894 | @@ -306,20 +345,14 @@ |
2895 | EXPECT_CALL(*mock_buffer_factory, create_buffer(_,_,_)) |
2896 | .Times(1); |
2897 | |
2898 | - auto surface = std::make_shared<MirSurface> (connection.get(), |
2899 | - *client_comm_channel, |
2900 | - logger, |
2901 | - mock_buffer_factory, |
2902 | - params, |
2903 | - &empty_callback, |
2904 | - nullptr); |
2905 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, mock_buffer_factory, input_platform, params, nullptr, &empty_callback, nullptr); |
2906 | |
2907 | auto wait_handle = surface->get_create_wait_handle(); |
2908 | wait_handle->wait_for_result(); |
2909 | |
2910 | EXPECT_CALL(*mock_buffer_factory, create_buffer(_,_,_)) |
2911 | .Times(1); |
2912 | - auto buffer_wait_handle = surface->next_buffer(&empty_surface_callback, (void*) NULL); |
2913 | + auto buffer_wait_handle = surface->next_buffer(&empty_surface_callback, nullptr); |
2914 | buffer_wait_handle->wait_for_result(); |
2915 | } |
2916 | |
2917 | @@ -328,12 +361,11 @@ |
2918 | // Can't simply use memcmp() on the whole struct because age is not sent over the wire |
2919 | if (package.data_items != arg.data_items) |
2920 | return false; |
2921 | + // Note we can not compare the fd's directly as they may change when being sent over the wire. |
2922 | if (package.fd_items != arg.fd_items) |
2923 | return false; |
2924 | if (memcmp(package.data, arg.data, sizeof(package.data[0]) * package.data_items)) |
2925 | return false; |
2926 | - if (memcmp(package.fd, arg.fd, sizeof(package.fd[0]) * package.fd_items)) |
2927 | - return false; |
2928 | if (package.stride != arg.stride) |
2929 | return false; |
2930 | return true; |
2931 | @@ -349,13 +381,8 @@ |
2932 | .WillOnce(DoAll(SaveArg<0>(&submitted_package), |
2933 | Return(mock_buffer_factory->emptybuffer))); |
2934 | |
2935 | - auto surface = std::make_shared<MirSurface> (connection.get(), |
2936 | - *client_comm_channel, |
2937 | - logger, |
2938 | - mock_buffer_factory, |
2939 | - params, |
2940 | - &empty_callback, |
2941 | - nullptr); |
2942 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, mock_buffer_factory, input_platform, params, nullptr, &empty_callback, nullptr); |
2943 | + |
2944 | auto wait_handle = surface->get_create_wait_handle(); |
2945 | wait_handle->wait_for_result(); |
2946 | |
2947 | @@ -375,13 +402,8 @@ |
2948 | .WillOnce(DoAll(SaveArg<1>(&sz), |
2949 | Return(mock_buffer_factory->emptybuffer))); |
2950 | |
2951 | - auto surface = std::make_shared<MirSurface> (connection.get(), |
2952 | - *client_comm_channel, |
2953 | - logger, |
2954 | - mock_buffer_factory, |
2955 | - params, |
2956 | - &empty_callback, |
2957 | - nullptr); |
2958 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, mock_buffer_factory, input_platform, params, nullptr, &empty_callback, nullptr); |
2959 | + |
2960 | auto wait_handle = surface->get_create_wait_handle(); |
2961 | wait_handle->wait_for_result(); |
2962 | |
2963 | @@ -400,13 +422,8 @@ |
2964 | .WillOnce(DoAll(SaveArg<1>(&sz), |
2965 | Return(mock_buffer_factory->emptybuffer))); |
2966 | |
2967 | - auto surface = std::make_shared<MirSurface> (connection.get(), |
2968 | - *client_comm_channel, |
2969 | - logger, |
2970 | - mock_buffer_factory, |
2971 | - params, |
2972 | - &empty_callback, |
2973 | - nullptr); |
2974 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, mock_buffer_factory, input_platform, params, nullptr, &empty_callback, nullptr); |
2975 | + |
2976 | auto wait_handle = surface->get_create_wait_handle(); |
2977 | wait_handle->wait_for_result(); |
2978 | |
2979 | @@ -425,13 +442,7 @@ |
2980 | .WillOnce(DoAll(SaveArg<2>(&pf), |
2981 | Return(mock_buffer_factory->emptybuffer))); |
2982 | |
2983 | - auto surface = std::make_shared<MirSurface> (connection.get(), |
2984 | - *client_comm_channel, |
2985 | - logger, |
2986 | - mock_buffer_factory, |
2987 | - params, |
2988 | - &empty_callback, |
2989 | - nullptr); |
2990 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, mock_buffer_factory, input_platform, params, nullptr, &empty_callback, nullptr); |
2991 | |
2992 | auto wait_handle = surface->get_create_wait_handle(); |
2993 | wait_handle->wait_for_result(); |
2994 | @@ -439,6 +450,46 @@ |
2995 | EXPECT_EQ(pf, geom::PixelFormat::abgr_8888); |
2996 | } |
2997 | |
2998 | + |
2999 | + |
3000 | +namespace |
3001 | +{ |
3002 | +static void null_event_callback(MirSurface*, MirEvent*, void*) |
3003 | +{ |
3004 | +} |
3005 | +} |
3006 | + |
3007 | +TEST_F(MirClientSurfaceTest, input_fd_used_to_create_input_thread_when_delegate_specified) |
3008 | +{ |
3009 | + using namespace ::testing; |
3010 | + |
3011 | + auto mock_input_platform = std::make_shared<mt::MockClientInputPlatform>(); |
3012 | + auto mock_input_thread = std::make_shared<mt::MockInputReceiverThread>(); |
3013 | + MirEventDelegate delegate = {null_event_callback, nullptr}; |
3014 | + |
3015 | + EXPECT_CALL(*mock_buffer_factory, create_buffer(_,_,_)).Times(2); |
3016 | + |
3017 | + EXPECT_CALL(*mock_input_platform, create_input_thread(_, _)).Times(1) |
3018 | + .WillOnce(Return(mock_input_thread)); |
3019 | + EXPECT_CALL(*mock_input_thread, start()).Times(1); |
3020 | + EXPECT_CALL(*mock_input_thread, stop()).Times(1); |
3021 | + |
3022 | + { |
3023 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, |
3024 | + mock_buffer_factory, mock_input_platform, params, &delegate, &empty_callback, nullptr); |
3025 | + auto wait_handle = surface->get_create_wait_handle(); |
3026 | + wait_handle->wait_for_result(); |
3027 | + } |
3028 | + |
3029 | + { |
3030 | + // This surface should not trigger a call to the input platform as no input delegate is specified. |
3031 | + auto surface = std::make_shared<MirSurface> (connection.get(), *client_comm_channel, logger, |
3032 | + mock_buffer_factory, mock_input_platform, params, nullptr, &empty_callback, nullptr); |
3033 | + auto wait_handle = surface->get_create_wait_handle(); |
3034 | + wait_handle->wait_for_result(); |
3035 | + } |
3036 | +} |
3037 | + |
3038 | TEST_F(MirClientSurfaceTest, get_buffer_returns_last_received_buffer_package) |
3039 | { |
3040 | using namespace testing; |
3041 | @@ -450,7 +501,9 @@ |
3042 | *client_comm_channel, |
3043 | logger, |
3044 | mock_buffer_factory, |
3045 | + input_platform, |
3046 | params, |
3047 | + nullptr, |
3048 | &empty_callback, |
3049 | nullptr); |
3050 | auto wait_handle = surface->get_create_wait_handle(); |
3051 | @@ -478,7 +531,9 @@ |
3052 | *client_comm_channel, |
3053 | logger, |
3054 | mock_buffer_factory, |
3055 | + input_platform, |
3056 | params, |
3057 | + nullptr, |
3058 | &empty_callback, |
3059 | nullptr); |
3060 | surface->get_create_wait_handle()->wait_for_result(); |
3061 | |
3062 | === modified file 'tests/unit-tests/input/android/test_android_input_application_handle.cpp' |
3063 | --- tests/unit-tests/input/android/test_android_input_application_handle.cpp 2013-03-29 16:51:35 +0000 |
3064 | +++ tests/unit-tests/input/android/test_android_input_application_handle.cpp 2013-04-03 18:49:21 +0000 |
3065 | @@ -20,8 +20,6 @@ |
3066 | |
3067 | #include "mir/input/session_target.h" |
3068 | |
3069 | -#include "mir_test/fake_shared.h" |
3070 | - |
3071 | #include <gtest/gtest.h> |
3072 | #include <gmock/gmock.h> |
3073 | |
3074 | @@ -29,7 +27,6 @@ |
3075 | |
3076 | namespace mi = mir::input; |
3077 | namespace mia = mi::android; |
3078 | -namespace mt = mir::test; |
3079 | |
3080 | namespace |
3081 | { |
3082 | @@ -44,15 +41,30 @@ |
3083 | { |
3084 | using namespace ::testing; |
3085 | std::string const testing_session_name = "Cats"; |
3086 | - MockSessionHandle session; |
3087 | + auto session = std::make_shared<MockSessionHandle>(); |
3088 | |
3089 | - EXPECT_CALL(session, name()).Times(AtLeast(1)) |
3090 | + EXPECT_CALL(*session, name()).Times(AtLeast(1)) |
3091 | .WillRepeatedly(Return(testing_session_name)); |
3092 | - mia::InputApplicationHandle application_handle(mt::fake_shared(session)); |
3093 | + mia::InputApplicationHandle application_handle(session); |
3094 | EXPECT_TRUE(application_handle.updateInfo()); |
3095 | auto info = application_handle.getInfo(); |
3096 | EXPECT_EQ(INT_MAX, info->dispatchingTimeout); |
3097 | EXPECT_EQ(droidinput::String8(testing_session_name.c_str()), info->name); |
3098 | } |
3099 | |
3100 | +TEST(AndroidInputApplicationHandle, does_not_own_session) |
3101 | +{ |
3102 | + using namespace ::testing; |
3103 | + std::string const testing_session_name = "Let it Grow"; |
3104 | + |
3105 | + auto session = std::make_shared<MockSessionHandle>(); |
3106 | + EXPECT_CALL(*session, name()).Times(AtLeast(1)) |
3107 | + .WillRepeatedly(Return(testing_session_name)); |
3108 | + |
3109 | + mia::InputApplicationHandle application_handle(session); |
3110 | + EXPECT_TRUE(application_handle.updateInfo()); |
3111 | + session.reset(); |
3112 | + EXPECT_FALSE(application_handle.updateInfo()); |
3113 | + |
3114 | +} |
3115 | |
3116 | |
3117 | === modified file 'tests/unit-tests/input/android/test_android_input_lexicon.cpp' |
3118 | --- tests/unit-tests/input/android/test_android_input_lexicon.cpp 2013-03-13 08:09:52 +0000 |
3119 | +++ tests/unit-tests/input/android/test_android_input_lexicon.cpp 2013-04-03 18:49:21 +0000 |
3120 | @@ -15,8 +15,8 @@ |
3121 | * |
3122 | * Authored by: Robert Carr <robert.carr@canonical.com> |
3123 | */ |
3124 | -#include "src/server/input/android/android_input_lexicon.h" |
3125 | -// Is this the right place for this header? Will eventually be included by clients. |
3126 | + |
3127 | +#include "mir/input/android/android_input_lexicon.h" |
3128 | #include "mir_toolkit/input/event.h" |
3129 | |
3130 | #include <androidfw/Input.h> |
3131 | @@ -25,7 +25,7 @@ |
3132 | #include <gmock/gmock.h> |
3133 | |
3134 | namespace mi = mir::input; |
3135 | -namespace mia = mir::input::android; |
3136 | +namespace miat = mir::input::android::transport; |
3137 | |
3138 | TEST(AndroidInputLexicon, translates_key_events) |
3139 | { |
3140 | @@ -48,7 +48,7 @@ |
3141 | down_time, event_time); |
3142 | |
3143 | MirEvent mir_ev; |
3144 | - mia::Lexicon::translate(android_key_ev, mir_ev); |
3145 | + miat::Lexicon::translate(android_key_ev, mir_ev); |
3146 | |
3147 | // Common event properties |
3148 | EXPECT_EQ(device_id, mir_ev.device_id); |
3149 | @@ -121,7 +121,7 @@ |
3150 | event_time, pointer_count, &pointer_properties, &pointer_coords); |
3151 | |
3152 | MirEvent mir_ev; |
3153 | - mia::Lexicon::translate(android_motion_ev, mir_ev); |
3154 | + miat::Lexicon::translate(android_motion_ev, mir_ev); |
3155 | |
3156 | // Common event properties |
3157 | EXPECT_EQ(device_id, mir_ev.device_id); |
3158 | |
3159 | === modified file 'tests/unit-tests/input/android/test_android_input_window_handle.cpp' |
3160 | --- tests/unit-tests/input/android/test_android_input_window_handle.cpp 2013-03-29 16:51:35 +0000 |
3161 | +++ tests/unit-tests/input/android/test_android_input_window_handle.cpp 2013-04-03 18:49:21 +0000 |
3162 | @@ -80,7 +80,7 @@ |
3163 | |
3164 | auto info = handle.getInfo(); |
3165 | |
3166 | - EXPECT_EQ(testing_surface_name, info->name); |
3167 | + EXPECT_EQ(droidinput::String8(testing_surface_name.c_str()), info->name); |
3168 | |
3169 | EXPECT_EQ(testing_server_fd, info->inputChannel->getFd()); |
3170 |
Jenkins will fail due to MIR_INPUT_ USE_ANDROID_ TYPES=false