Mir

Merge lp:~andreas-pokorny/mir/use-input-channel-to-send-input into lp:mir

Proposed by Andreas Pokorny
Status: Rejected
Rejected by: Andreas Pokorny
Proposed branch: lp:~andreas-pokorny/mir/use-input-channel-to-send-input
Merge into: lp:mir
Diff against target: 378 lines (+181/-18)
9 files modified
include/server/mir/input/input_channel.h (+4/-1)
include/test/mir_test_doubles/stub_input_channel.h (+3/-0)
src/server/input/android/android_input_channel.cpp (+100/-2)
src/server/input/android/android_input_channel.h (+10/-3)
src/server/input/android/android_input_window_handle.cpp (+11/-3)
tests/acceptance-tests/test_client_input.cpp (+39/-1)
tests/mir_test_framework/stubbed_server_configuration.cpp (+12/-8)
tests/unit-tests/input/android/test_android_input_window_handle.cpp (+1/-0)
tests/unit-tests/scene/test_surface.cpp (+1/-0)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/use-input-channel-to-send-input
Reviewer Review Type Date Requested Status
Daniel d'Andrada (community) Needs Fixing
Robert Carr (community) Needs Fixing
Alan Griffiths Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Kevin DuBois (community) Needs Information
Review via email: mp+215450@code.launchpad.net

Commit message

Add send_event to InputChannel - to be able to dispatch user input events to the client surfaces.

Description of the change

Adds a method to the InputChannel to send MirEvents to clients. This is necessary to implement a custom InputDispatcher outside of mir - hence without access to the adopted android input stack.

To post a comment you must log in.
Revision history for this message
Kevin DuBois (kdub) wrote :

send_event(uint32_t seq, MirEvent)
as someone calling send_event, how do I arrange seq; is a particular sequence needed? Would it be better to have AndroidInputChannel manage the sequence if a particular ordering is required?

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

24 + virtual void send_event(uint32_t seq, MirEvent const& event) const = 0;

Like Kevin says: What is the significance of seq? Why do I need it to send an event?

~~~~

77 +void react_to_result(droidinput::status_t result)

This seems a bad name. Vis:

142 + react_to_result(publisher.publishMotionEvent(seq, ...));

"check_result" is slightly better, "check" possibly better still.

~~~~

90 + channel = new droidinput::InputChannel(droidinput::String8("TODO: Name"), s_fd);

"TODO: Name" is a distracting choice. What is going on here?

review: Needs Fixing
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

Kevin:
> send_event(uint32_t seq, MirEvent)
> as someone calling send_event, how do I arrange seq;
> is a particular sequence needed? Would it be better to have
> AndroidInputChannel manage the sequence if a particular ordering is required?
Alan:
> 24 + virtual void send_event(uint32_t seq, MirEvent const& event) const =
> 0;
>
> Like Kevin says: What is the significance of seq? Why do I need it to send an
> event?

I believe down - motion - up sequences of events need to have the same sequence number. So I suspect AndroidInputChannel could keep track of press / release event occurrences. The sequence number must be unique for some time, as the client has to respond using the sequence number, as a form of ACK to the server.

> ~~~~
>
> 77 +void react_to_result(droidinput::status_t result)
>
> This seems a bad name. Vis:
>
> 142 + react_to_result(publisher.publishMotionEvent(seq, ...));
>
> "check_result" is slightly better, "check" possibly better still.

ack

> ~~~~
>
> 90 + channel = new droidinput::InputChannel(droidinput::String8("TODO:
> Name"), s_fd);
>
> "TODO: Name" is a distracting choice. What is going on here?

just moved the code - I believe we could use the surface name here instead. fixing that.

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

We talked a little about seq_id on IRC:

< anpok> dandrader: i would keep the current mir::input::InputDispatcher rather stable wrt further refactorings, but InputChannel .. I have to change rather sooner..
18:52 < anpok> or the thing to dispatch the input too
18:52 < dandrader> anpok, what's wrong with InputChannel?
18:53 < racarr__> one thing is send_event(seq_id, MirEvent) is weird because the caller cant know how to use seq_id really so its weird as a public interface
18:53 < anpok> it has to be non null :) and should not collide with other input sequences
18:54 < anpok> and nobody reads the ACK signals that come back from the input reader..
18:54 < racarr__> indeed but they will
18:54 < anpok> I only discovered that part today
18:54 < dandrader> racarr__, true
18:54 < racarr__> and if it has to be non null and not collide and thats all
18:54 < racarr__> then it should just be hidden inside the object

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

79 (missing spaces), 143, 166 (wrong indentation), 310 (trailing line):
whitespace.

Definitely use surface named for TODO: Name now...that was an artifact of interface inadequacies long past...sorry for never coming and fixing my own todo ><. Only used for logging (which is redundantly named elsewhere iirc) anyway

Given seq_id cleanup as part of dispatcher split this is basically good to go to unblock qt compositor I think

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

That's too low level. It's the android::InputDispatcher responsibility to shepherd events through android::InputChannels.

What is needed is something like a mir::input::Surface::consume_event(MirEvent) that, under
the hood, calls eventually android::InputDispatcher::notifyMotion(event,
surface->input_channel). Doing exactly what
MirSurfaceItem::dispatchTouchEventToMirInputChannel from lp:~unity-team/+junk
/qpa-mirserver does.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

So in the end we will have to go all the way and refactor android::InputDispatcher already now. :(

Making it only shepherd events through android::InputChannels (exactly like its stripped-down version existing in lp:~unity-team/+junk/qpa-mirserver) and leaving the responsibility of selecting which input channel gets the input event coming out of the android::InputReader to another entity (in the qt compositor case, the QQuickWindow dispatch logic that selects the qml item that will receive incoming input) that receives all input coming out of android::InputReader and calls mir::input::Surface::consume_event on the surface it decides that should receive the event, if any.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> So in the end we will have to go all the way and refactor
> android::InputDispatcher already now. :(
>
> Making it only shepherd events through android::InputChannels (exactly like
> its stripped-down version existing in lp:~unity-team/+junk/qpa-mirserver) and
> leaving the responsibility of selecting which input channel gets the input
> event coming out of the android::InputReader to another entity (in the qt
> compositor case, the QQuickWindow dispatch logic that selects the qml item
> that will receive incoming input) that receives all input coming out of
> android::InputReader and calls mir::input::Surface::consume_event on the
> surface it decides that should receive the event, if any.

Then, that stripped down android::InputDispatcher should probably be renamed to something else to avoid confusion since the selection of the recipient of incoming input events is what a event/input dispatcher is supposed to do.

Unmerged revisions

1545. By Andreas Pokorny

Add send_event to InputChannel - for sending events to the client fd.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/server/mir/input/input_channel.h'
--- include/server/mir/input/input_channel.h 2013-08-28 03:41:48 +0000
+++ include/server/mir/input/input_channel.h 2014-04-11 16:00:27 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright © 2013 Canonical Ltd.2 * Copyright © 2013-2014 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,5 * under the terms of the GNU General Public License version 3,
@@ -19,6 +19,8 @@
19#ifndef MIR_INPUT_INPUT_CHANNEL_H_19#ifndef MIR_INPUT_INPUT_CHANNEL_H_
20#define MIR_INPUT_INPUT_CHANNEL_H_20#define MIR_INPUT_INPUT_CHANNEL_H_
2121
22#include "mir_toolkit/event.h"
23
22namespace mir24namespace mir
23{25{
24namespace input26namespace input
@@ -32,6 +34,7 @@
3234
33 virtual int client_fd() const = 0;35 virtual int client_fd() const = 0;
34 virtual int server_fd() const = 0;36 virtual int server_fd() const = 0;
37 virtual void send_event(uint32_t seq, MirEvent const& event) const = 0;
3538
36protected:39protected:
37 InputChannel() = default;40 InputChannel() = default;
3841
=== modified file 'include/test/mir_test_doubles/stub_input_channel.h'
--- include/test/mir_test_doubles/stub_input_channel.h 2013-08-28 03:41:48 +0000
+++ include/test/mir_test_doubles/stub_input_channel.h 2014-04-11 16:00:27 +0000
@@ -48,6 +48,9 @@
48 {48 {
49 return input_fd;49 return input_fd;
50 }50 }
51 void send_event(uint32_t /*seq*/, MirEvent const& /*event*/) const override
52 {
53 }
51 int input_fd;54 int input_fd;
52};55};
5356
5457
=== modified file 'src/server/input/android/android_input_channel.cpp'
--- src/server/input/android/android_input_channel.cpp 2014-03-06 06:05:17 +0000
+++ src/server/input/android/android_input_channel.cpp 2014-04-11 16:00:27 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright © 2013 Canonical Ltd.2 * Copyright © 2013-2014 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,5 * under the terms of the GNU General Public License version 3,
@@ -14,21 +14,44 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 * Andreas Pokorny <andreas.pokorny@canonical.com>
17 */18 */
1819
19#include "android_input_channel.h"20#include "android_input_channel.h"
2021
21#include <androidfw/InputTransport.h>22#include <androidfw/InputTransport.h>
23#include <std/Errors.h>
24
25#include <boost/exception/errinfo_errno.hpp>
26#include <boost/throw_exception.hpp>
27
28#include <cmath>
2229
23#include <unistd.h>30#include <unistd.h>
2431
25namespace mia = mir::input::android;32namespace mia = mir::input::android;
26namespace droidinput = android;33namespace droidinput = android;
2734
35namespace
36{
37void react_to_result(droidinput::status_t result)
38{
39 if (result!=droidinput::OK)
40 {
41 BOOST_THROW_EXCEPTION(boost::enable_error_info(std::runtime_error("Failure sending input event ")) << boost::errinfo_errno(result));
42 }
43}
44}
45
28mia::AndroidInputChannel::AndroidInputChannel()46mia::AndroidInputChannel::AndroidInputChannel()
29{47{
30
31 droidinput::InputChannel::openInputFdPair(s_fd, c_fd);48 droidinput::InputChannel::openInputFdPair(s_fd, c_fd);
49 channel = new droidinput::InputChannel(droidinput::String8("TODO: Name"), s_fd);
50}
51
52droidinput::sp<droidinput::InputChannel> mia::AndroidInputChannel::get_android_channel() const
53{
54 return channel;
32}55}
3356
34mia::AndroidInputChannel::~AndroidInputChannel()57mia::AndroidInputChannel::~AndroidInputChannel()
@@ -46,3 +69,78 @@
46{69{
47 return s_fd;70 return s_fd;
48}71}
72
73void mia::AndroidInputChannel::send_event(uint32_t seq, MirEvent const& event) const
74{
75 switch(event.type)
76 {
77 case mir_event_type_key:
78 send_key_event(seq, event.key);
79 break;
80 case mir_event_type_motion:
81 send_motion_event(seq, event.motion);
82 break;
83 default:
84 break;
85 }
86}
87
88void mia::AndroidInputChannel::send_motion_event(uint32_t seq, MirMotionEvent const& event) const
89{
90 droidinput::PointerCoords coords[MIR_INPUT_EVENT_MAX_POINTER_COUNT];
91 droidinput::PointerProperties properties[MIR_INPUT_EVENT_MAX_POINTER_COUNT];
92 for (size_t i = 0; i < event.pointer_count; i++)
93 {
94 // TODO this assumes that: x == raw_x + x_offset;
95 // here x,y is used instead of the raw co-ordinates and offset is set to zero
96 coords[i].setAxisValue(AMOTION_EVENT_AXIS_X, event.pointer_coordinates[i].x);
97 coords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, event.pointer_coordinates[i].y);
98
99 coords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, event.pointer_coordinates[i].touch_major);
100 coords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, event.pointer_coordinates[i].touch_minor);
101 coords[i].setAxisValue(AMOTION_EVENT_AXIS_SIZE, event.pointer_coordinates[i].size);
102 coords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, event.pointer_coordinates[i].pressure);
103 coords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, event.pointer_coordinates[i].orientation);
104 coords[i].setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, event.pointer_coordinates[i].vscroll);
105 coords[i].setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, event.pointer_coordinates[i].hscroll);
106 properties[i].toolType = event.pointer_coordinates[i].tool_type;
107 }
108
109 droidinput::InputPublisher publisher(channel);
110
111 react_to_result(publisher.publishMotionEvent(seq,
112 event.device_id,
113 event.source_id,
114 event.action,
115 static_cast<int32_t>(event.flags),
116 event.edge_flags,
117 static_cast<int32_t>(event.modifiers),
118 static_cast<int32_t>(event.button_state),
119 0.0f, // event.x_offset,
120 0.0f, // event.y_offset,
121 event.x_precision,
122 event.y_precision,
123 event.down_time,
124 event.event_time,
125 event.pointer_count,
126 properties,
127 coords));
128}
129
130void mia::AndroidInputChannel::send_key_event(uint32_t seq, MirKeyEvent const& event) const
131{
132 droidinput::InputPublisher publisher(channel);
133
134 react_to_result(publisher.publishKeyEvent(seq,
135 event.device_id,
136 event.source_id,
137 event.action,
138 event.flags,
139 event.key_code,
140 event.scan_code,
141 event.modifiers,
142 event.repeat_count,
143 event.down_time,
144 event.event_time));
145}
146
49147
=== modified file 'src/server/input/android/android_input_channel.h'
--- src/server/input/android/android_input_channel.h 2013-08-28 03:41:48 +0000
+++ src/server/input/android/android_input_channel.h 2014-04-11 16:00:27 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright © 2013 Canonical Ltd.2 * Copyright © 2013-2014 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,5 * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 * Andreas Pokorny <andreas.pokorny@canonical.com>
17 */18 */
1819
19#ifndef MIR_INPUT_ANDROID_INPUT_CHANNEL_H_20#ifndef MIR_INPUT_ANDROID_INPUT_CHANNEL_H_
@@ -22,6 +23,7 @@
22#include "mir/input/input_channel.h"23#include "mir/input/input_channel.h"
2324
24#include <utils/StrongPointer.h>25#include <utils/StrongPointer.h>
26#include <androidfw/InputTransport.h>
2527
26namespace android28namespace android
27{29{
@@ -43,15 +45,20 @@
43 explicit AndroidInputChannel();45 explicit AndroidInputChannel();
44 virtual ~AndroidInputChannel();46 virtual ~AndroidInputChannel();
4547
46 int client_fd() const;48 int client_fd() const override;
47 int server_fd() const;49 int server_fd() const override;
50 void send_event(uint32_t seq, MirEvent const& event) const override;
4851
52 droidinput::sp<droidinput::InputChannel> get_android_channel() const;
49protected:53protected:
50 AndroidInputChannel(AndroidInputChannel const&) = delete;54 AndroidInputChannel(AndroidInputChannel const&) = delete;
51 AndroidInputChannel& operator=(AndroidInputChannel const&) = delete;55 AndroidInputChannel& operator=(AndroidInputChannel const&) = delete;
5256
53private:57private:
54 int s_fd, c_fd;58 int s_fd, c_fd;
59 droidinput::sp<droidinput::InputChannel> channel;
60 void send_key_event(uint32_t seq, MirKeyEvent const& event) const;
61 void send_motion_event(uint32_t seq, MirMotionEvent const& event) const;
55};62};
5663
57}64}
5865
=== modified file 'src/server/input/android/android_input_window_handle.cpp'
--- src/server/input/android/android_input_window_handle.cpp 2014-03-06 06:05:17 +0000
+++ src/server/input/android/android_input_window_handle.cpp 2014-04-11 16:00:27 +0000
@@ -18,6 +18,7 @@
1818
19#include "android_input_window_handle.h"19#include "android_input_window_handle.h"
20#include "android_input_application_handle.h"20#include "android_input_application_handle.h"
21#include "android_input_channel.h"
2122
22#include "mir/input/input_channel.h"23#include "mir/input/input_channel.h"
23#include "mir/input/surface.h"24#include "mir/input/surface.h"
@@ -64,9 +65,16 @@
64 {65 {
65 mInfo = new WindowInfo(surface);66 mInfo = new WindowInfo(surface);
6667
67 // TODO: How can we avoid recreating the InputChannel which the InputChannelFactory has already created?68 std::shared_ptr<AndroidInputChannel> droidchannel = std::dynamic_pointer_cast<AndroidInputChannel>(input_channel);
68 mInfo->inputChannel = new droidinput::InputChannel(droidinput::String8("TODO: Name"),69 if (droidchannel)
69 input_channel->server_fd());70 {
71 mInfo->inputChannel = droidchannel->get_android_channel();
72 }
73 else
74 {
75 mInfo->inputChannel = new droidinput::InputChannel(droidinput::String8("TODO: Name"),
76 input_channel->server_fd());
77 }
70 }78 }
7179
72 auto surface_size = surface->size();80 auto surface_size = surface->size();
7381
=== modified file 'tests/acceptance-tests/test_client_input.cpp'
--- tests/acceptance-tests/test_client_input.cpp 2014-04-04 14:42:55 +0000
+++ tests/acceptance-tests/test_client_input.cpp 2014-04-11 16:00:27 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright © 2013 Canonical Ltd.2 * Copyright © 2013-2014 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as5 * it under the terms of the GNU General Public License version 3 as
@@ -14,11 +14,13 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 * Andreas Pokorny <andreas.pokorny@canonical.com>
17 */18 */
1819
19#include "mir/graphics/display.h"20#include "mir/graphics/display.h"
20#include "mir/shell/surface_creation_parameters.h"21#include "mir/shell/surface_creation_parameters.h"
21#include "mir/shell/placement_strategy.h"22#include "mir/shell/placement_strategy.h"
23#include "mir/input/input_channel.h"
22#include "mir/scene/surface_coordinator.h"24#include "mir/scene/surface_coordinator.h"
23#include "mir/scene/surface.h"25#include "mir/scene/surface.h"
24#include "src/server/scene/session_container.h"26#include "src/server/scene/session_container.h"
@@ -613,3 +615,39 @@
613615
614 launch_client_process(*client);616 launch_client_process(*client);
615}617}
618
619TEST_F(TestClientInput, send_mir_events_with_input_channel)
620{
621 using namespace ::testing;
622
623 static std::string const test_client_name = "1";
624
625 mtf::CrossProcessSync fence;
626
627 MirEvent key_event;
628 memset(&key_event,0,sizeof(key_event));
629 key_event.type = mir_event_type_key;
630 key_event.key.action= mir_key_action_down;
631
632 auto server_config = make_event_producing_server(fence, 1,
633 [&](mtf::InputTestingServerConfiguration& server)
634 {
635 server.the_session_container()->for_each([&](std::shared_ptr<ms::Session> const& session) -> void
636 {
637 session->default_surface()->input_channel()->send_event(1,key_event);
638 });
639
640 });
641 launch_server_process(*server_config);
642
643 auto client_config = make_event_expecting_client(fence,
644 [&](MockHandler& handler, mt::WaitCondition& events_received)
645 {
646 using namespace ::testing;
647 InSequence seq;
648 EXPECT_CALL(handler, handle_input(mt::KeyDownEvent())).Times(1)
649 .WillOnce(mt::WakeUp(&events_received));
650
651 });
652 launch_client_process(*client_config);
653}
616654
=== modified file 'tests/mir_test_framework/stubbed_server_configuration.cpp'
--- tests/mir_test_framework/stubbed_server_configuration.cpp 2014-03-27 09:46:09 +0000
+++ tests/mir_test_framework/stubbed_server_configuration.cpp 2014-04-11 16:00:27 +0000
@@ -217,14 +217,18 @@
217217
218struct StubInputChannel : public mi::InputChannel218struct StubInputChannel : public mi::InputChannel
219{219{
220 int client_fd() const220 int client_fd() const override
221 {221 {
222 return 0;222 return 0;
223 }223 }
224224
225 int server_fd() const225 int server_fd() const override
226 {226 {
227 return 0;227 return 0;
228 }
229
230 void send_event(uint32_t /*seq*/, MirEvent const& /*event*/) const override
231 {
228 }232 }
229};233};
230234
231235
=== modified file 'tests/unit-tests/input/android/test_android_input_window_handle.cpp'
--- tests/unit-tests/input/android/test_android_input_window_handle.cpp 2014-03-26 14:20:14 +0000
+++ tests/unit-tests/input/android/test_android_input_window_handle.cpp 2014-04-11 16:00:27 +0000
@@ -52,6 +52,7 @@
52{52{
53 MOCK_CONST_METHOD0(client_fd, int());53 MOCK_CONST_METHOD0(client_fd, int());
54 MOCK_CONST_METHOD0(server_fd, int());54 MOCK_CONST_METHOD0(server_fd, int());
55 MOCK_CONST_METHOD2(send_event,void(uint32_t /*seq*/, MirEvent const& /*event*/));
55};56};
5657
57}58}
5859
=== modified file 'tests/unit-tests/scene/test_surface.cpp'
--- tests/unit-tests/scene/test_surface.cpp 2014-03-31 16:51:06 +0000
+++ tests/unit-tests/scene/test_surface.cpp 2014-04-11 16:00:27 +0000
@@ -52,6 +52,7 @@
52{52{
53 MOCK_CONST_METHOD0(server_fd, int());53 MOCK_CONST_METHOD0(server_fd, int());
54 MOCK_CONST_METHOD0(client_fd, int());54 MOCK_CONST_METHOD0(client_fd, int());
55 MOCK_CONST_METHOD2(send_event,void(uint32_t /*seq*/, MirEvent const& /*event*/));
55};56};
56}57}
5758

Subscribers

People subscribed via source and target branches