Merge lp:~andreas-pokorny/mir/fix-1639749 into lp:mir
- fix-1639749
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Daniel van Vugt |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3842 |
Proposed branch: | lp:~andreas-pokorny/mir/fix-1639749 |
Merge into: | lp:mir |
Prerequisite: | lp:~andreas-pokorny/mir/preserve-framebuffer-on-compatible-configurations-in-stub-graphics |
Diff against target: |
515 lines (+220/-43) 10 files modified
include/test/mir/test/event_matchers.h (+45/-0) src/client/event_printer.cpp (+3/-3) src/server/graphics/nested/input_platform.cpp (+8/-1) src/server/input/surface_input_dispatcher.cpp (+42/-1) tests/acceptance-tests/test_client_cookie.cpp (+1/-2) tests/acceptance-tests/test_client_input.cpp (+10/-17) tests/acceptance-tests/test_confined_pointer.cpp (+4/-8) tests/acceptance-tests/test_nested_input.cpp (+77/-2) tests/unit-tests/input/test_nested_input_platform.cpp (+27/-0) tests/unit-tests/input/test_surface_input_dispatcher.cpp (+3/-9) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/fix-1639749 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Kevin DuBois (community) | Approve | ||
Alexandros Frantzis (community) | Approve | ||
Review via email: mp+310568@code.launchpad.net |
Commit message
Fix duplicated motion events on enter and filter out enter events in nested input platform
If the surface input dispatcher detects that the surface underneath the mouse cursor has changed it would send a leave event to the old window (containing the relative mouse motion) and the current position. The new window receives an enter event, and also the relative motion. After that the original event was sent. That led to sending the relative motion twice. It now depends on whether the original event contained a state change other than the motion itself. If so the motion change is removed from the original event, if not the event is discarded.
Description of the change
This MP contains two behavior corrections in SurfaceInputDis
The bulk of the test changes is related to the fact that we are only sending a single event when a new window is underneath the mouse cursor.
Mir CI Bot (mir-ci-bot) wrote : | # |
Daniel van Vugt (vanvugt) wrote : | # |
^^^
Bug 1570698 again. Although Brandon and Anpok rewrote the underlying code and the test case recently so possibly the failures have a different cause now.
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3817
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3818
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'include/test/mir/test/event_matchers.h' |
2 | --- include/test/mir/test/event_matchers.h 2016-11-11 07:56:09 +0000 |
3 | +++ include/test/mir/test/event_matchers.h 2016-11-23 15:19:48 +0000 |
4 | @@ -377,6 +377,21 @@ |
5 | return true; |
6 | } |
7 | |
8 | +MATCHER_P2(PointerEnterEventWithPosition, x, y, "") |
9 | +{ |
10 | + auto pev = maybe_pointer_event(to_address(arg)); |
11 | + if (pev == nullptr) |
12 | + return false; |
13 | + if (mir_pointer_event_action(pev) != mir_pointer_action_enter) |
14 | + return false; |
15 | + if (mir_pointer_event_axis_value(pev, mir_pointer_axis_x) != x) |
16 | + return false; |
17 | + if (mir_pointer_event_axis_value(pev, mir_pointer_axis_y) != y) |
18 | + return false; |
19 | + return true; |
20 | +} |
21 | + |
22 | + |
23 | MATCHER_P(PointerEventWithModifiers, modifiers, "") |
24 | { |
25 | auto pev = maybe_pointer_event(to_address(arg)); |
26 | @@ -404,6 +419,26 @@ |
27 | return true; |
28 | } |
29 | |
30 | +MATCHER_P2(PointerEnterEventWithDiff, expect_dx, expect_dy, "") |
31 | +{ |
32 | + auto pev = maybe_pointer_event(to_address(arg)); |
33 | + if (pev == nullptr) |
34 | + return false; |
35 | + if (mir_pointer_event_action(pev) != mir_pointer_action_enter) |
36 | + return false; |
37 | + auto const error = 0.00001f; |
38 | + auto const actual_dx = mir_pointer_event_axis_value(pev, |
39 | + mir_pointer_axis_relative_x); |
40 | + if (std::abs(expect_dx - actual_dx) > error) |
41 | + return false; |
42 | + auto const actual_dy = mir_pointer_event_axis_value(pev, |
43 | + mir_pointer_axis_relative_y); |
44 | + if (std::abs(expect_dy - actual_dy) > error) |
45 | + return false; |
46 | + return true; |
47 | +} |
48 | + |
49 | + |
50 | MATCHER_P4(TouchEventInDirection, x0, y0, x1, y1, "") |
51 | { |
52 | auto tev = maybe_touch_event(to_address(arg)); |
53 | @@ -541,6 +576,16 @@ |
54 | return false; |
55 | } |
56 | |
57 | +MATCHER_P2(DeviceStateWithPosition, x, y, "") |
58 | +{ |
59 | + auto as_address = to_address(arg); |
60 | + if (mir_event_get_type(as_address) != mir_event_type_input_device_state) |
61 | + return false; |
62 | + auto device_state = mir_event_get_input_device_state_event(as_address); |
63 | + return x == mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_x) && |
64 | + y == mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_y); |
65 | +} |
66 | + |
67 | } |
68 | } |
69 | |
70 | |
71 | === modified file 'src/client/event_printer.cpp' |
72 | --- src/client/event_printer.cpp 2016-11-11 06:59:42 +0000 |
73 | +++ src/client/event_printer.cpp 2016-11-23 15:19:48 +0000 |
74 | @@ -218,7 +218,7 @@ |
75 | << mir_keyboard_event_action(key_event) |
76 | << ", code=" << mir_keyboard_event_key_code(key_event) |
77 | << ", scan=" << mir_keyboard_event_scan_code(key_event) << ", modifiers=" << std::hex |
78 | - << mir_keyboard_event_modifiers(key_event) << std::dec << ')'; |
79 | + << static_cast<MirInputEventModifier>(mir_keyboard_event_modifiers(key_event)) << std::dec << ')'; |
80 | } |
81 | case mir_input_event_type_touch: |
82 | { |
83 | @@ -236,7 +236,7 @@ |
84 | << ", minor=" << mir_touch_event_axis_value(touch_event, index, mir_touch_axis_touch_minor) |
85 | << ", size=" << mir_touch_event_axis_value(touch_event, index, mir_touch_axis_size) << '}'; |
86 | |
87 | - return out << ", modifiers=" << mir_touch_event_modifiers(touch_event) << ')'; |
88 | + return out << ", modifiers=" << static_cast<MirInputEventModifier>(mir_touch_event_modifiers(touch_event)) << ')'; |
89 | } |
90 | case mir_input_event_type_pointer: |
91 | { |
92 | @@ -255,7 +255,7 @@ |
93 | << ", dy=" << mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y) |
94 | << ", vscroll=" << mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll) |
95 | << ", hscroll=" << mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll) |
96 | - << ", modifiers=" << mir_pointer_event_modifiers(pointer_event) << ')'; |
97 | + << ", modifiers=" << static_cast<MirInputEventModifier>(mir_pointer_event_modifiers(pointer_event)) << ')'; |
98 | } |
99 | default: |
100 | return out << "<INVALID>"; |
101 | |
102 | === modified file 'src/server/graphics/nested/input_platform.cpp' |
103 | --- src/server/graphics/nested/input_platform.cpp 2016-11-11 06:59:42 +0000 |
104 | +++ src/server/graphics/nested/input_platform.cpp 2016-11-23 15:19:48 +0000 |
105 | @@ -39,6 +39,13 @@ |
106 | namespace |
107 | { |
108 | |
109 | +auto filter_pointer_action(MirPointerAction action) |
110 | +{ |
111 | + return (action == mir_pointer_action_enter || action == mir_pointer_action_leave) |
112 | + ? mir_pointer_action_motion |
113 | + : action; |
114 | +} |
115 | + |
116 | mgn::UniqueInputConfig make_empty_config() |
117 | { |
118 | return mgn::UniqueInputConfig(nullptr, [](MirInputConfig const*){}); |
119 | @@ -122,7 +129,7 @@ |
120 | auto y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y); |
121 | auto new_event = builder->pointer_event( |
122 | event_time, |
123 | - mir_pointer_event_action(pointer_event), |
124 | + filter_pointer_action(mir_pointer_event_action(pointer_event)), |
125 | mir_pointer_event_buttons(pointer_event), |
126 | x + frame.top_left.x.as_int(), |
127 | y + frame.top_left.y.as_int(), |
128 | |
129 | === modified file 'src/server/input/surface_input_dispatcher.cpp' |
130 | --- src/server/input/surface_input_dispatcher.cpp 2016-11-11 07:56:09 +0000 |
131 | +++ src/server/input/surface_input_dispatcher.cpp 2016-11-23 15:19:48 +0000 |
132 | @@ -23,6 +23,7 @@ |
133 | #include "mir/scene/observer.h" |
134 | #include "mir/scene/surface.h" |
135 | #include "mir/events/event_builders.h" |
136 | +#include "mir_toolkit/mir_cookie.h" |
137 | |
138 | #include <string.h> |
139 | |
140 | @@ -69,6 +70,37 @@ |
141 | std::function<void(ms::Surface*)> const on_removed; |
142 | }; |
143 | |
144 | +void deliver_without_relative_motion(std::shared_ptr<mi::Surface> const& surface, MirEvent const* ev) |
145 | +{ |
146 | + auto const* input_ev = mir_event_get_input_event(ev); |
147 | + auto const* pev = mir_input_event_get_pointer_event(input_ev); |
148 | + std::vector<uint8_t> cookie_data; |
149 | + if (mir_input_event_has_cookie(input_ev)) |
150 | + { |
151 | + auto cookie = mir_input_event_get_cookie(input_ev); |
152 | + cookie_data.resize(mir_cookie_buffer_size(cookie)); |
153 | + mir_cookie_to_buffer(cookie, cookie_data.data(), mir_cookie_buffer_size(cookie)); |
154 | + mir_cookie_release(cookie); |
155 | + } |
156 | + auto const& bounds = surface->input_bounds(); |
157 | + |
158 | + auto to_deliver = mev::make_event(mir_input_event_get_device_id(input_ev), |
159 | + std::chrono::nanoseconds{mir_input_event_get_event_time(input_ev)}, |
160 | + cookie_data, |
161 | + mir_pointer_event_modifiers(pev), |
162 | + mir_pointer_event_action(pev), |
163 | + mir_pointer_event_buttons(pev), |
164 | + mir_pointer_event_axis_value(pev, mir_pointer_axis_x), |
165 | + mir_pointer_event_axis_value(pev, mir_pointer_axis_y), |
166 | + 0.0f, |
167 | + 0.0f, |
168 | + 0.0f, |
169 | + 0.0f); |
170 | + |
171 | + mev::transform_positions(*to_deliver, geom::Displacement{bounds.top_left.x.as_int(), bounds.top_left.y.as_int()}); |
172 | + surface->consume(to_deliver.get()); |
173 | +} |
174 | + |
175 | void deliver(std::shared_ptr<mi::Surface> const& surface, MirEvent const* ev) |
176 | { |
177 | auto to_deliver = mev::clone_event(*ev); |
178 | @@ -287,7 +319,16 @@ |
179 | { |
180 | pointer_state.gesture_owner = target; |
181 | } |
182 | - deliver(target, ev); |
183 | + |
184 | + if (sent_ev) |
185 | + { |
186 | + if (action != mir_pointer_action_motion) |
187 | + deliver_without_relative_motion(target, ev); |
188 | + } |
189 | + else |
190 | + { |
191 | + deliver(target, ev); |
192 | + } |
193 | return true; |
194 | } |
195 | return false; |
196 | |
197 | === modified file 'tests/acceptance-tests/test_client_cookie.cpp' |
198 | --- tests/acceptance-tests/test_client_cookie.cpp 2016-07-18 07:38:38 +0000 |
199 | +++ tests/acceptance-tests/test_client_cookie.cpp 2016-11-23 15:19:48 +0000 |
200 | @@ -177,10 +177,9 @@ |
201 | |
202 | TEST_F(ClientCookies, pointer_motion_events_do_not_have_cookies) |
203 | { |
204 | - // with movement generates 2 events |
205 | fake_pointer->emit_event(mis::a_pointer_event().with_movement(1, 1)); |
206 | |
207 | - int events = 2; |
208 | + int events = 1; |
209 | if (wait_for_n_events(events, this)) |
210 | { |
211 | std::lock_guard<std::mutex> lk(mutex); |
212 | |
213 | === modified file 'tests/acceptance-tests/test_client_input.cpp' |
214 | --- tests/acceptance-tests/test_client_input.cpp 2016-11-15 20:53:57 +0000 |
215 | +++ tests/acceptance-tests/test_client_input.cpp 2016-11-23 15:19:48 +0000 |
216 | @@ -317,8 +317,7 @@ |
217 | |
218 | // We should see the cursor enter |
219 | InSequence seq; |
220 | - EXPECT_CALL(first_client, handle_input(mt::PointerEnterEvent())); |
221 | - EXPECT_CALL(first_client, handle_input(mt::PointerEventWithPosition(surface_width - 1, surface_height - 1))); |
222 | + EXPECT_CALL(first_client, handle_input(mt::PointerEnterEventWithPosition(surface_width - 1, surface_height - 1))); |
223 | EXPECT_CALL(first_client, handle_input(mt::PointerLeaveEvent())) |
224 | .WillOnce(mt::WakeUp(&first_client.all_events_received)); |
225 | // But we should not receive an event for the second movement outside of our surface! |
226 | @@ -337,8 +336,8 @@ |
227 | Client first_client(new_connection(), first); |
228 | |
229 | InSequence seq; |
230 | - EXPECT_CALL(first_client, handle_input(mt::PointerEnterEvent())); |
231 | - EXPECT_CALL(first_client, handle_input(AllOf(mt::PointerEventWithPosition(1, 1), mt::PointerEventWithDiff(1, 1)))); |
232 | + EXPECT_CALL(first_client, handle_input(AllOf(mt::PointerEnterEventWithPosition(1, 1), |
233 | + mt::PointerEnterEventWithDiff(1, 1)))); |
234 | EXPECT_CALL(first_client, handle_input(AllOf(mt::PointerEventWithPosition(2, 2), mt::PointerEventWithDiff(1, 1)))); |
235 | EXPECT_CALL(first_client, handle_input(AllOf(mt::PointerEventWithPosition(3, 3), mt::PointerEventWithDiff(1, 1)))); |
236 | EXPECT_CALL(first_client, handle_input(AllOf(mt::PointerEventWithPosition(2, 2), mt::PointerEventWithDiff(-1, -1)))); |
237 | @@ -434,16 +433,14 @@ |
238 | |
239 | { |
240 | InSequence seq; |
241 | - EXPECT_CALL(first_client, handle_input(mt::PointerEnterEvent())); |
242 | - EXPECT_CALL(first_client, handle_input(mt::PointerEventWithPosition(client_width - 1, client_height - 1))); |
243 | + EXPECT_CALL(first_client, handle_input(mt::PointerEnterEventWithPosition(client_width - 1, client_height - 1))); |
244 | EXPECT_CALL(first_client, handle_input(mt::PointerLeaveEvent())) |
245 | .WillOnce(mt::WakeUp(&first_client.all_events_received)); |
246 | } |
247 | |
248 | { |
249 | InSequence seq; |
250 | - EXPECT_CALL(second_client, handle_input(mt::PointerEnterEvent())); |
251 | - EXPECT_CALL(second_client, handle_input(mt::PointerEventWithPosition(client_width - 1, client_height - 1))) |
252 | + EXPECT_CALL(second_client, handle_input(mt::PointerEnterEventWithPosition(client_width - 1, client_height - 1))) |
253 | .WillOnce(mt::WakeUp(&second_client.all_events_received)); |
254 | } |
255 | |
256 | @@ -556,14 +553,12 @@ |
257 | Client first_client(new_connection(), first); |
258 | Client second_client(new_connection(), second); |
259 | |
260 | - EXPECT_CALL(second_client, handle_input(mt::PointerEnterEvent())).Times(AnyNumber()); |
261 | - EXPECT_CALL(second_client, handle_input(mt::PointerLeaveEvent())).Times(AnyNumber()); |
262 | - EXPECT_CALL(second_client, handle_input(mt::PointerEventWithPosition(1, 1))) |
263 | + EXPECT_CALL(second_client, handle_input(mt::PointerEnterEventWithPosition(1, 1))) |
264 | .WillOnce(mt::WakeUp(&second_client.all_events_received)); |
265 | |
266 | - EXPECT_CALL(first_client, handle_input(mt::PointerEnterEvent())).Times(AnyNumber()); |
267 | - EXPECT_CALL(first_client, handle_input(mt::PointerLeaveEvent())).Times(AnyNumber()); |
268 | - EXPECT_CALL(first_client, handle_input(mt::PointerEventWithPosition(2, 2))) |
269 | + EXPECT_CALL(second_client, handle_input(mt::PointerLeaveEvent())).Times(AnyNumber()); |
270 | + |
271 | + EXPECT_CALL(first_client, handle_input(mt::PointerEnterEventWithPosition(2, 2))) |
272 | .WillOnce(mt::WakeUp(&first_client.all_events_received)); |
273 | |
274 | // We send one event and then hide the surface on top before sending the next. |
275 | @@ -870,11 +865,9 @@ |
276 | ASSERT_TRUE(shell->wait_for_modify_surface(5s)); |
277 | |
278 | // We verify that we don't receive the first shaped out button event. |
279 | - EXPECT_CALL(client, handle_input(mt::PointerEnterEvent())); |
280 | - EXPECT_CALL(client, handle_input(mt::PointerEventWithPosition(1, 1))); |
281 | + EXPECT_CALL(client, handle_input(mt::PointerEnterEventWithPosition(1, 1))); |
282 | EXPECT_CALL(client, handle_input(mt::ButtonDownEvent(1, 1))) |
283 | .WillOnce(mt::WakeUp(&client.all_events_received)); |
284 | - |
285 | |
286 | fake_mouse->emit_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down)); |
287 | fake_mouse->emit_event(mis::a_button_up_event().of_button(BTN_LEFT).with_action(mis::EventAction::Up)); |
288 | |
289 | === modified file 'tests/acceptance-tests/test_confined_pointer.cpp' |
290 | --- tests/acceptance-tests/test_confined_pointer.cpp 2016-11-02 05:07:18 +0000 |
291 | +++ tests/acceptance-tests/test_confined_pointer.cpp 2016-11-23 15:19:48 +0000 |
292 | @@ -215,8 +215,7 @@ |
293 | Client client(new_connection(), first); |
294 | |
295 | InSequence seq; |
296 | - EXPECT_CALL(client, handle_input(mt::PointerEnterEvent())); |
297 | - EXPECT_CALL(client, handle_input(mt::PointerEventWithPosition(surface_width / 2, 0))); |
298 | + EXPECT_CALL(client, handle_input(mt::PointerEnterEventWithPosition(surface_width / 2, 0))); |
299 | EXPECT_CALL(client, handle_input(AllOf(mt::PointerEventWithPosition(surface_width - 1, 0), |
300 | mt::PointerEventWithDiff(surface_width * 2, 0)))); |
301 | EXPECT_CALL(client, handle_input(AllOf(mt::PointerEventWithPosition(surface_width - 1, 0), |
302 | @@ -236,8 +235,7 @@ |
303 | Client client(new_connection(), first); |
304 | |
305 | InSequence seq; |
306 | - EXPECT_CALL(client, handle_input(mt::PointerEnterEvent())); |
307 | - EXPECT_CALL(client, handle_input(mt::PointerEventWithPosition(surface_width - 1, 0))); |
308 | + EXPECT_CALL(client, handle_input(mt::PointerEnterEventWithPosition(surface_width - 1, 0))); |
309 | EXPECT_CALL(client, handle_input(AllOf(mt::PointerEventWithPosition(surface_width - 1, 0), mt::PointerEventWithDiff(10, 0)))) |
310 | .WillOnce(mt::WakeUp(&client.all_events_received)); |
311 | |
312 | @@ -265,8 +263,7 @@ |
313 | resized_signaled.wait_for(1s); |
314 | |
315 | InSequence seq; |
316 | - EXPECT_CALL(client, handle_input(mt::PointerEnterEvent())); |
317 | - EXPECT_CALL(client, handle_input(mt::PointerEventWithPosition(surface_width + 100 - 1, 0))); |
318 | + EXPECT_CALL(client, handle_input(mt::PointerEnterEventWithPosition(surface_width + 100 - 1, 0))); |
319 | EXPECT_CALL(client, handle_input(AllOf(mt::PointerEventWithPosition(surface_width + 100 - 1, 0), mt::PointerEventWithDiff(10, 0)))) |
320 | .WillOnce(mt::WakeUp(&client.all_events_received)); |
321 | |
322 | @@ -295,8 +292,7 @@ |
323 | std::this_thread::sleep_for(1s); |
324 | |
325 | InSequence seq; |
326 | - EXPECT_CALL(client_2, handle_input(mt::PointerEnterEvent())); |
327 | - EXPECT_CALL(client_2, handle_input(mt::PointerEventWithPosition(0, 0))); |
328 | + EXPECT_CALL(client_2, handle_input(mt::PointerEnterEventWithPosition(0, 0))); |
329 | EXPECT_CALL(client_2, handle_input(mt::PointerEventWithPosition(surface_width - 1, 0))) |
330 | .WillOnce(mt::WakeUp(&client_2.all_events_received)); |
331 | |
332 | |
333 | === modified file 'tests/acceptance-tests/test_nested_input.cpp' |
334 | --- tests/acceptance-tests/test_nested_input.cpp 2016-10-12 06:03:15 +0000 |
335 | +++ tests/acceptance-tests/test_nested_input.cpp 2016-11-23 15:19:48 +0000 |
336 | @@ -69,8 +69,7 @@ |
337 | |
338 | std::vector<mir::geometry::Rectangle> const display_geometry |
339 | { |
340 | - {{ 0, 0}, { 640, 480}}, |
341 | - {{480, 0}, {1920, 1080}} |
342 | + {{ 0, 0}, {1920, 1080}} |
343 | }; |
344 | |
345 | struct NestedServerWithMockEventFilter : mtf::HeadlessNestedServerRunner |
346 | @@ -118,6 +117,14 @@ |
347 | std::make_shared<NiceMock<mtd::MockInputDeviceObserver>>()}; |
348 | }; |
349 | |
350 | +struct NestedInputWithMouse : NestedInput |
351 | +{ |
352 | + std::unique_ptr<mtf::FakeInputDevice> fake_mouse{ |
353 | + mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer}) |
354 | + }; |
355 | + MockEventFilter nested_event_filter; |
356 | +}; |
357 | + |
358 | struct ExposedSurface |
359 | { |
360 | public: |
361 | @@ -301,3 +308,71 @@ |
362 | client_to_nested_event_received.wait_for(2s); |
363 | client_to_host_event_received.wait_for(2s); |
364 | } |
365 | + |
366 | +TEST_F(NestedInputWithMouse, mouse_pointer_coordinates_in_nested_server_are_accumulated) |
367 | +{ |
368 | + auto const initial_movement_x = 30; |
369 | + auto const initial_movement_y = 30; |
370 | + auto const second_movement_x = 5; |
371 | + auto const second_movement_y = -2; |
372 | + |
373 | + mt::Signal devices_ready; |
374 | + mt::Signal event_received; |
375 | + EXPECT_CALL(nested_event_filter, handle(mt::InputDeviceStateEvent())) |
376 | + .WillOnce(DoAll(mt::WakeUp(&devices_ready), Return(true))); |
377 | + |
378 | + EXPECT_CALL(nested_event_filter, |
379 | + handle(AllOf(mt::PointerEventWithPosition(initial_movement_x, initial_movement_y), |
380 | + mt::PointerEventWithDiff(initial_movement_x, initial_movement_y)))) |
381 | + .WillOnce(DoAll(mt::WakeUp(&event_received), Return(true))); |
382 | + |
383 | + NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
384 | + ExposedSurface client_to_nested_mir(nested_mir.new_connection()); |
385 | + client_to_nested_mir.ready_to_accept_events.wait_for(1s); |
386 | + |
387 | + devices_ready.wait_for(2s); |
388 | + |
389 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(initial_movement_x, initial_movement_y)); |
390 | + event_received.wait_for(2s); |
391 | + |
392 | + event_received.reset(); |
393 | + |
394 | + EXPECT_CALL(nested_event_filter, |
395 | + handle(AllOf(mt::PointerEventWithPosition(initial_movement_x + second_movement_x, initial_movement_y + second_movement_y), |
396 | + mt::PointerEventWithDiff(second_movement_x, second_movement_y)))) |
397 | + .WillOnce(DoAll(mt::WakeUp(&event_received), Return(true))); |
398 | + |
399 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(second_movement_x, second_movement_y)); |
400 | + event_received.wait_for(2s); |
401 | +} |
402 | + |
403 | +TEST_F(NestedInputWithMouse, mouse_pointer_position_is_in_sync_with_host_server) |
404 | +{ |
405 | + int const x[] = {30, -10, 10}; |
406 | + int const y[] = {30, 100, 50}; |
407 | + int const initial_x = x[0] + x[1]; |
408 | + int const initial_y = y[0] + y[1]; |
409 | + int const final_x = initial_x + x[2]; |
410 | + int const final_y = initial_y + y[2]; |
411 | + |
412 | + mt::Signal devices_ready; |
413 | + mt::Signal event_received; |
414 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(x[0], y[0])); |
415 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(x[1], y[1])); |
416 | + |
417 | + EXPECT_CALL(nested_event_filter, handle( |
418 | + mt::DeviceStateWithPosition(initial_x, initial_y))) |
419 | + .WillOnce(DoAll(mt::WakeUp(&devices_ready), Return(true))); |
420 | + EXPECT_CALL(nested_event_filter, |
421 | + handle(AllOf(mt::PointerEventWithPosition(final_x, final_y), |
422 | + mt::PointerEventWithDiff(x[2], y[2])))) |
423 | + .WillOnce(DoAll(mt::WakeUp(&event_received), Return(true))); |
424 | + |
425 | + NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
426 | + ExposedSurface client_to_nested_mir(nested_mir.new_connection()); |
427 | + client_to_nested_mir.ready_to_accept_events.wait_for(1s); |
428 | + devices_ready.wait_for(2s); |
429 | + |
430 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(x[2], y[2])); |
431 | + event_received.wait_for(2s); |
432 | +} |
433 | |
434 | === modified file 'tests/unit-tests/input/test_nested_input_platform.cpp' |
435 | --- tests/unit-tests/input/test_nested_input_platform.cpp 2016-10-27 14:31:48 +0000 |
436 | +++ tests/unit-tests/input/test_nested_input_platform.cpp 2016-11-23 15:19:48 +0000 |
437 | @@ -174,3 +174,30 @@ |
438 | mock_host_connection.event_callback(*mev::make_event(a_keyboard.id(), 141ns, cookie, mir_keyboard_action_down, 0, |
439 | scan_code, mir_input_event_modifier_none), source_surface); |
440 | } |
441 | + |
442 | +TEST_F(TestNestedInputPlatform, replaces_enter_events_as_motion_event) |
443 | +{ |
444 | + auto nested_input_device = capture_input_device(a_mouse); |
445 | + NiceMock<mtd::MockInputSink> event_sink; |
446 | + mi::DefaultEventBuilder builder(MirInputDeviceId{18}, mir::cookie::Authority::create(), mt::fake_shared(mock_seat)); |
447 | + |
448 | + ASSERT_THAT(nested_input_device, Ne(nullptr)); |
449 | + nested_input_device->start(&event_sink, &builder); |
450 | + |
451 | + EXPECT_CALL(event_sink, |
452 | + handle_input(AllOf( |
453 | + mt::PointerEventWithPosition(60.0f, 35.0f), mt::PointerEventWithDiff(60.0f, 35.0f)))); |
454 | + std::vector<uint8_t> cookie; |
455 | + |
456 | + auto event = mev::make_event(a_mouse.id(), |
457 | + 141ns, |
458 | + cookie, |
459 | + mir_input_event_modifier_none, |
460 | + mir_pointer_action_enter, |
461 | + 0, |
462 | + 60.0f, 35.0f, |
463 | + 0, 0, |
464 | + 60.0f, 35.0f); |
465 | + |
466 | + mock_host_connection.event_callback(*event, source_surface); |
467 | +} |
468 | |
469 | === modified file 'tests/unit-tests/input/test_surface_input_dispatcher.cpp' |
470 | --- tests/unit-tests/input/test_surface_input_dispatcher.cpp 2016-11-11 07:56:09 +0000 |
471 | +++ tests/unit-tests/input/test_surface_input_dispatcher.cpp 2016-11-23 15:19:48 +0000 |
472 | @@ -294,7 +294,6 @@ |
473 | |
474 | InSequence seq; |
475 | EXPECT_CALL(*surface, consume(mt::PointerEnterEvent())).Times(1); |
476 | - EXPECT_CALL(*surface, consume(mt::PointerEventWithPosition(1, 0))).Times(1); |
477 | EXPECT_CALL(*surface, consume(mt::PointerLeaveEvent())).Times(1); |
478 | |
479 | dispatcher.start(); |
480 | @@ -312,10 +311,8 @@ |
481 | |
482 | InSequence seq; |
483 | EXPECT_CALL(*top_surface, consume(mt::PointerEnterEvent())).Times(1); |
484 | - EXPECT_CALL(*top_surface, consume(mt::PointerEventWithPosition(1, 0))).Times(1); |
485 | EXPECT_CALL(*surface, consume(mt::PointerEnterEvent())).Times(1); |
486 | - EXPECT_CALL(*surface, consume(mt::PointerEventWithPosition(1, 0))).Times(1); |
487 | - |
488 | + |
489 | dispatcher.start(); |
490 | |
491 | EXPECT_TRUE(dispatcher.dispatch(*pointer.move_to({1, 0}))); |
492 | @@ -334,12 +331,10 @@ |
493 | |
494 | InSequence seq; |
495 | EXPECT_CALL(*surface, consume(mt::PointerEnterEvent())).Times(1); |
496 | - EXPECT_CALL(*surface, consume(mt::PointerEventWithPosition(1, 1))).Times(1); |
497 | EXPECT_CALL(*surface, consume(mt::PointerLeaveEvent())).Times(1); |
498 | EXPECT_CALL(*another_surface, consume(mt::PointerEnterEvent())).Times(1); |
499 | - EXPECT_CALL(*another_surface, consume(mt::PointerEventWithPosition(1, 1))).Times(1); |
500 | EXPECT_CALL(*another_surface, consume(mt::PointerLeaveEvent())).Times(1); |
501 | - |
502 | + |
503 | dispatcher.start(); |
504 | |
505 | EXPECT_TRUE(dispatcher.dispatch(*pointer.move_to({1, 1}))); |
506 | @@ -419,8 +414,7 @@ |
507 | EXPECT_CALL(*surface, consume(mt::PointerEnterEvent())).Times(1); |
508 | EXPECT_CALL(*surface, consume(mt::ButtonDownEvent(0,0))).Times(1); |
509 | EXPECT_CALL(*another_surface, consume(mt::PointerEnterEvent())).Times(1); |
510 | - EXPECT_CALL(*another_surface, consume(mt::PointerEventWithPosition(1,1))).Times(1); |
511 | - |
512 | + |
513 | dispatcher.start(); |
514 | |
515 | EXPECT_TRUE(dispatcher.dispatch(*ev_1)); |
FAILED: Continuous integration, rev:3817 /mir-jenkins. ubuntu. com/job/ mir-ci/ 2143/ /mir-jenkins. ubuntu. com/job/ build-mir/ 2775/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/2840 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 2832 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 2832 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= yakkety/ 2832 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= yakkety/ 2804/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2804 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2804/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2804 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2804/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 2804 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 2804/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 2804 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 2804/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2804 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2804/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 2143/rebuild
https:/