Mir

Merge lp:~alan-griffiths/mir/dont-handle-nested-input-on-rpc-thread into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Brandon Schaefer
Approved revision: no longer in the source branch.
Merged at revision: 4197
Proposed branch: lp:~alan-griffiths/mir/dont-handle-nested-input-on-rpc-thread
Merge into: lp:mir
Diff against target: 193 lines (+82/-12)
2 files modified
src/server/graphics/nested/input_platform.cpp (+77/-12)
tests/unit-tests/input/test_nested_input_platform.cpp (+5/-0)
To merge this branch: bzr merge lp:~alan-griffiths/mir/dont-handle-nested-input-on-rpc-thread
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Andreas Pokorny (community) Approve
Mir CI Bot continuous-integration Approve
Review via email: mp+326234@code.launchpad.net

Commit message

We recently changes the input transport to arrive on the RPC Thread of clients.

Mir-on-Mir therefore needs another thread for processing input as the handling of input can reasonably make blocking client API calls.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:4201
https://mir-jenkins.ubuntu.com/job/mir-ci/3461/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4723
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4881
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4870
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4870
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4870
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4760/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4760/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4760/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4760/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4760/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4760/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4760/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4760
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4760/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/3461/rebuild

review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

I think this is reasonable to do - but there might be acceptance test troubles because now there are less order guarantees between certain state changes and input dispatching within the nested server.

Lgtm

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/server/graphics/nested/input_platform.cpp'
--- src/server/graphics/nested/input_platform.cpp 2017-05-08 03:04:26 +0000
+++ src/server/graphics/nested/input_platform.cpp 2017-06-23 16:26:45 +0000
@@ -33,6 +33,9 @@
33#include "mir/events/event_builders.h"33#include "mir/events/event_builders.h"
3434
35#include <chrono>35#include <chrono>
36#include <condition_variable>
37#include <thread>
38#include <queue>
3639
37namespace mi = mir::input;40namespace mi = mir::input;
38namespace mgn = mir::graphics::nested;41namespace mgn = mir::graphics::nested;
@@ -52,9 +55,68 @@
52 return mgn::UniqueInputConfig(nullptr, [](MirInputConfig const*){});55 return mgn::UniqueInputConfig(nullptr, [](MirInputConfig const*){});
53}56}
5457
55}58class Postman
5659{
57struct mgn::InputPlatform::InputDevice : mi::InputDevice60public:
61
62 void start_work();
63 void post(std::shared_ptr<MirEvent> const& event);
64 void stop_work();
65
66 mi::InputSink* destination{nullptr};
67
68private:
69 using EventQueue = std::queue<std::shared_ptr<MirEvent>>;
70
71 std::thread worker_thread;
72 std::mutex mutable mutex;
73 std::condition_variable work_cv;
74 EventQueue events;
75
76 void do_work();
77
78 std::shared_ptr<MirEvent> next_event();
79};
80
81void Postman::do_work()
82{
83 while (auto const event = next_event())
84 destination->handle_input(*event);
85}
86
87std::shared_ptr<MirEvent> Postman::next_event()
88{
89 EventQueue::value_type event;
90 {
91 std::unique_lock<decltype(mutex)> lock{mutex};
92 work_cv.wait(lock, [this] { return !events.empty(); });
93 event.swap(events.front());
94 events.pop();
95 }
96 return event;
97}
98
99void Postman::post(std::shared_ptr<MirEvent> const& event)
100{
101 std::lock_guard<decltype(mutex)> lock{mutex};
102 events.push(event);
103 work_cv.notify_one();
104}
105
106void Postman::start_work()
107{
108 worker_thread = std::thread([this] { do_work(); });
109}
110
111void Postman::stop_work()
112{
113 // We use a null event as a sentinel
114 post({});
115 worker_thread.join();
116}
117}
118
119struct mgn::InputPlatform::InputDevice : mi::InputDevice, Postman
58{120{
59public:121public:
60 InputDevice(MirInputDevice* dev, std::function<void()> config_change)122 InputDevice(MirInputDevice* dev, std::function<void()> config_change)
@@ -119,6 +181,12 @@
119 {181 {
120 this->destination = destination;182 this->destination = destination;
121 this->builder = builder;183 this->builder = builder;
184 start_work();
185 }
186
187 void post_event(std::shared_ptr<MirEvent> const event)
188 {
189 post(event);
122 }190 }
123191
124 void emit_event(MirInputEvent const* event, mir::geometry::Rectangle const& frame)192 void emit_event(MirInputEvent const* event, mir::geometry::Rectangle const& frame)
@@ -147,20 +215,19 @@
147 contact.touch_major = mir_touch_event_axis_value(touch_event, i, mir_touch_axis_touch_major);215 contact.touch_major = mir_touch_event_axis_value(touch_event, i, mir_touch_axis_touch_major);
148 contact.touch_minor = mir_touch_event_axis_value(touch_event, i, mir_touch_axis_touch_minor);216 contact.touch_minor = mir_touch_event_axis_value(touch_event, i, mir_touch_axis_touch_minor);
149 }217 }
150 destination->handle_input(*builder->touch_event(event_time, contacts));218 post_event(builder->touch_event(event_time, contacts));
151 break;219 break;
152 }220 }
153 case mir_input_event_type_key:221 case mir_input_event_type_key:
154 {222 {
155 auto const* key_event = mir_input_event_get_keyboard_event(event);223 auto const* key_event = mir_input_event_get_keyboard_event(event);
156224
157 auto new_kev = builder->key_event(225 post_event(builder->key_event(
158 event_time,226 event_time,
159 mir_keyboard_event_action(key_event),227 mir_keyboard_event_action(key_event),
160 mir_keyboard_event_key_code(key_event),228 mir_keyboard_event_key_code(key_event),
161 mir_keyboard_event_scan_code(key_event)229 mir_keyboard_event_scan_code(key_event)
162 );230 ));
163 destination->handle_input(*new_kev);
164 break;231 break;
165 }232 }
166 case mir_input_event_type_pointer:233 case mir_input_event_type_pointer:
@@ -168,7 +235,7 @@
168 auto const* pointer_event = mir_input_event_get_pointer_event(event);235 auto const* pointer_event = mir_input_event_get_pointer_event(event);
169 auto x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);236 auto x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
170 auto y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);237 auto y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
171 auto new_event = builder->pointer_event(238 post_event(builder->pointer_event(
172 event_time,239 event_time,
173 filter_pointer_action(mir_pointer_event_action(pointer_event)),240 filter_pointer_action(mir_pointer_event_action(pointer_event)),
174 mir_pointer_event_buttons(pointer_event),241 mir_pointer_event_buttons(pointer_event),
@@ -178,9 +245,7 @@
178 mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll),245 mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll),
179 mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x),246 mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x),
180 mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y)247 mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y)
181 );248 ));
182
183 destination->handle_input(*new_event);
184 break;249 break;
185 }250 }
186 default:251 default:
@@ -190,6 +255,7 @@
190255
191 void stop() override256 void stop() override
192 {257 {
258 stop_work();
193 this->destination = nullptr;259 this->destination = nullptr;
194 this->builder = nullptr;260 this->builder = nullptr;
195 }261 }
@@ -272,7 +338,6 @@
272338
273 MirInputDeviceId device_id;339 MirInputDeviceId device_id;
274 MirInputDevice* device{nullptr};340 MirInputDevice* device{nullptr};
275 mi::InputSink* destination{nullptr};
276 mi::EventBuilder* builder{nullptr};341 mi::EventBuilder* builder{nullptr};
277 mi::InputDeviceInfo device_info;342 mi::InputDeviceInfo device_info;
278 mir::optional_value<mi::PointerSettings> pointer_settings;343 mir::optional_value<mi::PointerSettings> pointer_settings;
279344
=== modified file 'tests/unit-tests/input/test_nested_input_platform.cpp'
--- tests/unit-tests/input/test_nested_input_platform.cpp 2017-05-08 03:04:26 +0000
+++ tests/unit-tests/input/test_nested_input_platform.cpp 2017-06-23 16:26:45 +0000
@@ -153,6 +153,8 @@
153 mock_host_connection.event_callback(*mev::make_event(a_mouse.id(), 12ns, cookie, mir_input_event_modifier_none,153 mock_host_connection.event_callback(*mev::make_event(a_mouse.id(), 12ns, cookie, mir_input_event_modifier_none,
154 mir_pointer_action_motion, mir_pointer_button_primary, 23, 42,154 mir_pointer_action_motion, mir_pointer_button_primary, 23, 42,
155 0, 0, 12, 10), source_surface);155 0, 0, 12, 10), source_surface);
156
157 nested_input_device->stop();
156}158}
157159
158TEST_F(TestNestedInputPlatform, devices_forward_key_events)160TEST_F(TestNestedInputPlatform, devices_forward_key_events)
@@ -172,6 +174,7 @@
172174
173 mock_host_connection.event_callback(*mev::make_event(a_keyboard.id(), 141ns, cookie, mir_keyboard_action_down, 0,175 mock_host_connection.event_callback(*mev::make_event(a_keyboard.id(), 141ns, cookie, mir_keyboard_action_down, 0,
174 scan_code, mir_input_event_modifier_none), source_surface);176 scan_code, mir_input_event_modifier_none), source_surface);
177 nested_input_device->stop();
175}178}
176179
177TEST_F(TestNestedInputPlatform, replaces_enter_events_as_motion_event)180TEST_F(TestNestedInputPlatform, replaces_enter_events_as_motion_event)
@@ -199,6 +202,7 @@
199 60.0f, 35.0f);202 60.0f, 35.0f);
200203
201 mock_host_connection.event_callback(*event, source_surface);204 mock_host_connection.event_callback(*event, source_surface);
205 nested_input_device->stop();
202}206}
203207
204TEST_F(TestNestedInputPlatform, device_configurations_are_forwarded_to_host_connection)208TEST_F(TestNestedInputPlatform, device_configurations_are_forwarded_to_host_connection)
@@ -216,4 +220,5 @@
216 EXPECT_CALL(mock_host_connection, apply_input_configuration(_));220 EXPECT_CALL(mock_host_connection, apply_input_configuration(_));
217221
218 nested_input_device->apply_settings(left_handed);222 nested_input_device->apply_settings(left_handed);
223 nested_input_device->stop();
219}224}

Subscribers

People subscribed via source and target branches