Mir

Merge lp:~andreas-pokorny/mir/fix-1639749 into lp:mir

Proposed by Andreas Pokorny
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
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 SurfaceInputDispatcher and in the nested input platform. The former avoids sending an unnecessary motion event that would - if the client accumulates relative motion - lead to a wrong cursor position from the clients perspective. In the nested input platform we have to filter out enter events that are triggered by the fact that the nested session gets focused. Those are converted to regular motion events instead.

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.

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

FAILED: Continuous integration, rev:3817
https://mir-jenkins.ubuntu.com/job/mir-ci/2143/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2775/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2840
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2832
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2832
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2832
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2804/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2804
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2804/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2804
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2804/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2804
        deb: https://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
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2804
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2804/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2804
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2804/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
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.

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3817
https://mir-jenkins.ubuntu.com/job/mir-ci/2147/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2783
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2848
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2840
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2840
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2840
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2812
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2812/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2812
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2812/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2812
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2812/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2812
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2812/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2812
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2812/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2812
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2812/artifact/output/*zip*/output.zip

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

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

Looks good.

review: Approve
Revision history for this message
Kevin DuBois (kdub) wrote :

lgtm

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
https://mir-jenkins.ubuntu.com/job/mir-autolanding/805/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2920/console
    None: https://mir-jenkins.ubuntu.com/job/generic-land-mp/851/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2985
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2977
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2977
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2977
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2949/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2949/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2949/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2949/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2949/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2949/console

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3818
https://mir-jenkins.ubuntu.com/job/mir-ci/2258/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2925
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2990
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2982
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2982
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2982
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2954
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2954/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2954
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2954/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2954
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2954/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2954
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2954/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2954
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2954/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2954
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2954/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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));

Subscribers

People subscribed via source and target branches