Merge lp:~brandontschaefer/mir/pointer-confinement into lp:mir
- pointer-confinement
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Cemil Azizoglu |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3560 |
Proposed branch: | lp:~brandontschaefer/mir/pointer-confinement |
Merge into: | lp:mir |
Diff against target: |
1159 lines (+429/-17) 36 files modified
examples/server_example_canonical_window_manager.cpp (+5/-0) include/server/mir/scene/surface.h (+3/-0) include/server/mir/scene/surface_creation_parameters.h (+1/-0) include/server/mir/shell/abstract_shell.h (+7/-1) include/test/mir/test/doubles/stub_surface.h (+2/-0) src/client/mir_connection.cpp (+1/-0) src/include/server/mir/input/seat.h (+3/-0) src/include/server/mir/shell/window_management_info.h (+1/-1) src/protobuf/mir_protobuf.proto (+1/-0) src/server/frontend/session_mediator.cpp (+1/-0) src/server/input/basic_seat.cpp (+10/-0) src/server/input/basic_seat.h (+2/-0) src/server/input/seat_input_device_tracker.cpp (+29/-7) src/server/input/seat_input_device_tracker.h (+6/-0) src/server/scene/basic_surface.cpp (+14/-1) src/server/scene/basic_surface.h (+6/-0) src/server/scene/surface_allocator.cpp (+2/-0) src/server/shell/abstract_shell.cpp (+23/-1) src/server/shell/canonical_window_manager.cpp (+5/-0) src/server/shell/default_configuration.cpp (+2/-1) tests/acceptance-tests/CMakeLists.txt (+1/-0) tests/acceptance-tests/test_confined_pointer.cpp (+214/-0) tests/acceptance-tests/test_surface_placement.cpp (+1/-0) tests/include/mir/test/doubles/mock_input_seat.h (+3/-0) tests/include/mir/test/doubles/mock_surface.h (+1/-0) tests/include/mir/test/doubles/stub_scene_surface.h (+3/-0) tests/integration-tests/surface_composition.cpp (+1/-0) tests/integration-tests/test_surface_stack_with_compositor.cpp (+1/-0) tests/mir_test_framework/stub_surface.cpp (+10/-0) tests/unit-tests/input/test_seat_input_device_tracker.cpp (+36/-0) tests/unit-tests/scene/test_abstract_shell.cpp (+4/-1) tests/unit-tests/scene/test_basic_surface.cpp (+8/-2) tests/unit-tests/scene/test_session_manager.cpp (+1/-0) tests/unit-tests/scene/test_surface.cpp (+4/-1) tests/unit-tests/scene/test_surface_impl.cpp (+3/-1) tests/unit-tests/scene/test_surface_stack.cpp (+14/-0) |
To merge this branch: | bzr merge lp:~brandontschaefer/mir/pointer-confinement |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Cemil Azizoglu (community) | Approve | ||
Kevin DuBois (community) | Approve | ||
Chris Halse Rogers | Approve | ||
Andreas Pokorny (community) | Approve | ||
Review via email: mp+297941@code.launchpad.net |
Commit message
Implements pointer confinement for a surface as a spec.
Only works for a focus windows. The window manager is in charge of actually setting the surface to have pointer confinement if the spec is updated. Right now we need to depend on setting the seat in the abstract shell since its where we need to update the mouse events.
Description of the change
Implements pointer confinement for a surface as a spec.
Only works for a focus windows. The window manager is in charge of actually setting the surface to have pointer confinement if the spec is updated. Right now we need to depend on setting the seat in the abstract shell since its where we need to update the mouse events.
Mir CI Bot (mir-ci-bot) wrote : | # |
Brandon Schaefer (brandontschaefer) wrote : | # |
Need to implement this for SurfaceSpecParams (ie. the creation parms which are different then the normal SurfaceSpec struct!)
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3538
https:/
Executed test runs:
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:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3539
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
Not blocking: A piece is missing here: the handling of surface movements... I.e. imagine a window manager short cut that changes the window position on screen i.e. toggles form full screen to windows or back - without loosing focus.
I am not sure who should be in charge of that. In the past in mirserver we would use a surface change observer. With AbstractShell we might want to have a move_resize_
Codewise a suggestion:
void mi::SeatInputDe
+{
+ confine_function = [regions,
+ {
+ regions.
+ input_region-
+ };
+}
+
+void mi::SeatInputDe
+{
+ confine_function = [this](
+}
+
+void mi::SeatInputDe
+{
mir:
auto confined = old;
- input_region-
+ confine_
if (confined.x != old.x) cursor_x = confined.
if (confined.y != old.y) cursor_y = confined.
+}
+
+void mi::SeatInputDe
+{
+ cursor_x += mir_pointer_
+ cursor_y += mir_pointer_
+
+ confine_pointer();
and just let confine_function be a std::function<
hmm is that a needs fixing..
Brandon Schaefer (brandontschaefer) wrote : | # |
O i like that!
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3542
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Chris Halse Rogers (raof) wrote : | # |
747 -#include <gmock/gmock.h>
747 +#include "mir/input/
748 +#include "mir/test/
You've accidentally removed <gmock/gmock.h> and replaced it with (the unnecessary, I think?) gmock_fixes.h.
Not blocking, but if you need to update it for any other reason, please fix.
Other than that, looks fine.
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
25 + virtual void set_confine_
set_confine_
-------
285 + geometry:
s/pointer_
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
Looks good
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3544
https:/
Executed test runs:
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:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'examples/server_example_canonical_window_manager.cpp' |
2 | --- examples/server_example_canonical_window_manager.cpp 2016-05-04 01:48:16 +0000 |
3 | +++ examples/server_example_canonical_window_manager.cpp 2016-06-27 20:45:54 +0000 |
4 | @@ -416,6 +416,11 @@ |
5 | auto const state = handle_set_state(surface, modifications.state.value()); |
6 | surface->configure(mir_surface_attrib_state, state); |
7 | } |
8 | + |
9 | + if (modifications.confine_pointer.is_set()) |
10 | + { |
11 | + surface->set_confine_pointer_state(modifications.confine_pointer.value()); |
12 | + } |
13 | } |
14 | |
15 | void me::CanonicalWindowManagerPolicyCopy::handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface) |
16 | |
17 | === modified file 'include/server/mir/scene/surface.h' |
18 | --- include/server/mir/scene/surface.h 2016-05-03 06:55:25 +0000 |
19 | +++ include/server/mir/scene/surface.h 2016-06-27 20:45:54 +0000 |
20 | @@ -115,6 +115,9 @@ |
21 | std::string const& variant, std::string const& options) = 0; |
22 | virtual void rename(std::string const& title) = 0; |
23 | virtual void set_streams(std::list<StreamInfo> const& streams) = 0; |
24 | + |
25 | + virtual void set_confine_pointer_state(MirPointerConfinementState state) = 0; |
26 | + virtual MirPointerConfinementState confine_pointer_state() const = 0; |
27 | }; |
28 | } |
29 | } |
30 | |
31 | === modified file 'include/server/mir/scene/surface_creation_parameters.h' |
32 | --- include/server/mir/scene/surface_creation_parameters.h 2016-04-13 01:27:36 +0000 |
33 | +++ include/server/mir/scene/surface_creation_parameters.h 2016-06-27 20:45:54 +0000 |
34 | @@ -102,6 +102,7 @@ |
35 | mir::optional_value<std::vector<geometry::Rectangle>> input_shape; |
36 | mir::optional_value<MirShellChrome> shell_chrome; |
37 | mir::optional_value<std::vector<shell::StreamSpecification>> streams; |
38 | + mir::optional_value<MirPointerConfinementState> confine_pointer; |
39 | }; |
40 | |
41 | bool operator==(const SurfaceCreationParameters& lhs, const SurfaceCreationParameters& rhs); |
42 | |
43 | === modified file 'include/server/mir/shell/abstract_shell.h' |
44 | --- include/server/mir/shell/abstract_shell.h 2016-01-29 08:18:22 +0000 |
45 | +++ include/server/mir/shell/abstract_shell.h 2016-06-27 20:45:54 +0000 |
46 | @@ -26,6 +26,10 @@ |
47 | |
48 | namespace mir |
49 | { |
50 | +namespace input |
51 | +{ |
52 | +class Seat; |
53 | +} |
54 | namespace shell |
55 | { |
56 | class ShellReport; |
57 | @@ -41,7 +45,8 @@ |
58 | std::shared_ptr<scene::SessionCoordinator> const& session_coordinator, |
59 | std::shared_ptr<scene::PromptSessionManager> const& prompt_session_manager, |
60 | std::shared_ptr<ShellReport> const& report, |
61 | - WindowManagerBuilder const& wm_builder); |
62 | + WindowManagerBuilder const& wm_builder, |
63 | + std::shared_ptr<input::Seat> const& seat); |
64 | |
65 | ~AbstractShell() noexcept; |
66 | |
67 | @@ -122,6 +127,7 @@ |
68 | std::shared_ptr<scene::SessionCoordinator> const session_coordinator; |
69 | std::shared_ptr<scene::PromptSessionManager> const prompt_session_manager; |
70 | std::shared_ptr<WindowManager> const window_manager; |
71 | + std::shared_ptr<input::Seat> const seat; |
72 | |
73 | private: |
74 | std::shared_ptr<ShellReport> const report; |
75 | |
76 | === modified file 'include/test/mir/test/doubles/stub_surface.h' |
77 | --- include/test/mir/test/doubles/stub_surface.h 2016-01-29 08:18:22 +0000 |
78 | +++ include/test/mir/test/doubles/stub_surface.h 2016-06-27 20:45:54 +0000 |
79 | @@ -70,6 +70,8 @@ |
80 | void set_keymap(MirInputDeviceId id, std::string const& model, std::string const& layout, |
81 | std::string const& variant, std::string const& options) override; |
82 | void rename(std::string const& title) override; |
83 | + void set_confine_pointer_state(MirPointerConfinementState state) override; |
84 | + MirPointerConfinementState confine_pointer_state() const override; |
85 | }; |
86 | } |
87 | } |
88 | |
89 | === modified file 'src/client/mir_connection.cpp' |
90 | --- src/client/mir_connection.cpp 2016-06-24 01:19:33 +0000 |
91 | +++ src/client/mir_connection.cpp 2016-06-27 20:45:54 +0000 |
92 | @@ -129,6 +129,7 @@ |
93 | SERIALIZE_OPTION_IF_SET(width_inc); |
94 | SERIALIZE_OPTION_IF_SET(height_inc); |
95 | SERIALIZE_OPTION_IF_SET(shell_chrome); |
96 | + SERIALIZE_OPTION_IF_SET(confine_pointer); |
97 | // min_aspect is a special case (below) |
98 | // max_aspect is a special case (below) |
99 | |
100 | |
101 | === modified file 'src/include/server/mir/input/seat.h' |
102 | --- src/include/server/mir/input/seat.h 2016-05-03 06:55:25 +0000 |
103 | +++ src/include/server/mir/input/seat.h 2016-06-27 20:45:54 +0000 |
104 | @@ -21,6 +21,7 @@ |
105 | #define MIR_INPUT_SEAT_H_ |
106 | |
107 | #include "mir/geometry/rectangle.h" |
108 | +#include "mir/geometry/rectangles.h" |
109 | #include "mir_toolkit/event.h" |
110 | |
111 | #include <memory> |
112 | @@ -39,6 +40,8 @@ |
113 | virtual void remove_device(Device const& device) = 0; |
114 | virtual void dispatch_event(MirEvent& event) = 0; |
115 | virtual geometry::Rectangle get_rectangle_for(Device const& dev) = 0; |
116 | + virtual void set_confinement_regions(geometry::Rectangles const& regions) = 0; |
117 | + virtual void reset_confinement_regions() = 0; |
118 | private: |
119 | Seat(Seat const&) = delete; |
120 | Seat& operator=(Seat const&) = delete; |
121 | |
122 | === modified file 'src/include/server/mir/shell/window_management_info.h' |
123 | --- src/include/server/mir/shell/window_management_info.h 2016-06-07 19:23:52 +0000 |
124 | +++ src/include/server/mir/shell/window_management_info.h 2016-06-27 20:45:54 +0000 |
125 | @@ -75,7 +75,7 @@ |
126 | mir::optional_value<shell::SurfaceAspectRatio> min_aspect; |
127 | mir::optional_value<shell::SurfaceAspectRatio> max_aspect; |
128 | mir::optional_value<graphics::DisplayConfigurationOutputId> output_id; |
129 | - mir::optional_value<bool> confine_pointer; |
130 | + mir::optional_value<MirPointerConfinementState> confine_pointer; |
131 | |
132 | void init_titlebar(std::shared_ptr <scene::Surface> const& surface); |
133 | |
134 | |
135 | === modified file 'src/protobuf/mir_protobuf.proto' |
136 | --- src/protobuf/mir_protobuf.proto 2016-06-08 13:49:11 +0000 |
137 | +++ src/protobuf/mir_protobuf.proto 2016-06-27 20:45:54 +0000 |
138 | @@ -45,6 +45,7 @@ |
139 | repeated Rectangle input_shape = 22; |
140 | optional int32 shell_chrome = 24; |
141 | repeated StreamConfiguration stream = 25; |
142 | + optional int32 confine_pointer = 26; |
143 | } |
144 | |
145 | message SurfaceAspectRatio |
146 | |
147 | === modified file 'src/server/frontend/session_mediator.cpp' |
148 | --- src/server/frontend/session_mediator.cpp 2016-06-07 19:23:52 +0000 |
149 | +++ src/server/frontend/session_mediator.cpp 2016-06-27 20:45:54 +0000 |
150 | @@ -284,6 +284,7 @@ |
151 | COPY_IF_SET(width_inc); |
152 | COPY_IF_SET(height_inc); |
153 | COPY_IF_SET(shell_chrome); |
154 | + COPY_IF_SET(confine_pointer); |
155 | |
156 | #undef COPY_IF_SET |
157 | |
158 | |
159 | === modified file 'src/server/input/basic_seat.cpp' |
160 | --- src/server/input/basic_seat.cpp 2016-05-03 06:55:25 +0000 |
161 | +++ src/server/input/basic_seat.cpp 2016-06-27 20:45:54 +0000 |
162 | @@ -57,3 +57,13 @@ |
163 | // assumes that only the first output may have a touch screen associated to it. |
164 | return input_region->bounding_rectangle(); |
165 | } |
166 | + |
167 | +void mi::BasicSeat::set_confinement_regions(geometry::Rectangles const& regions) |
168 | +{ |
169 | + input_state_tracker.set_confinement_regions(regions); |
170 | +} |
171 | + |
172 | +void mi::BasicSeat::reset_confinement_regions() |
173 | +{ |
174 | + input_state_tracker.reset_confinement_regions(); |
175 | +} |
176 | |
177 | === modified file 'src/server/input/basic_seat.h' |
178 | --- src/server/input/basic_seat.h 2016-05-03 06:55:25 +0000 |
179 | +++ src/server/input/basic_seat.h 2016-06-27 20:45:54 +0000 |
180 | @@ -47,6 +47,8 @@ |
181 | void remove_device(Device const& device) override; |
182 | void dispatch_event(MirEvent& event) override; |
183 | geometry::Rectangle get_rectangle_for(Device const& dev) override; |
184 | + virtual void set_confinement_regions(geometry::Rectangles const& regions) override; |
185 | + virtual void reset_confinement_regions() override; |
186 | |
187 | private: |
188 | SeatInputDeviceTracker input_state_tracker; |
189 | |
190 | === modified file 'src/server/input/seat_input_device_tracker.cpp' |
191 | --- src/server/input/seat_input_device_tracker.cpp 2016-06-02 08:19:38 +0000 |
192 | +++ src/server/input/seat_input_device_tracker.cpp 2016-06-27 20:45:54 +0000 |
193 | @@ -37,13 +37,16 @@ |
194 | |
195 | namespace mi = mir::input; |
196 | namespace mev = mir::events; |
197 | +namespace geom = mir::geometry; |
198 | |
199 | mi::SeatInputDeviceTracker::SeatInputDeviceTracker(std::shared_ptr<InputDispatcher> const& dispatcher, |
200 | std::shared_ptr<TouchVisualizer> const& touch_visualizer, |
201 | std::shared_ptr<CursorListener> const& cursor_listener, |
202 | std::shared_ptr<InputRegion> const& input_region) |
203 | : dispatcher{dispatcher}, touch_visualizer{touch_visualizer}, cursor_listener{cursor_listener}, |
204 | - input_region{input_region}, modifier{0}, buttons{0} |
205 | + input_region{input_region}, modifier{0}, buttons{0}, |
206 | + confine_function{[input_region](mir::geometry::Point& pos) { input_region->confine(pos); }} |
207 | + |
208 | { |
209 | } |
210 | |
211 | @@ -210,16 +213,35 @@ |
212 | return buttons; |
213 | } |
214 | |
215 | -void mi::SeatInputDeviceTracker::update_cursor(MirPointerEvent const* event) |
216 | -{ |
217 | - cursor_x += mir_pointer_event_axis_value(event, mir_pointer_axis_relative_x); |
218 | - cursor_y += mir_pointer_event_axis_value(event, mir_pointer_axis_relative_y); |
219 | - |
220 | +void mi::SeatInputDeviceTracker::set_confinement_regions(geometry::Rectangles const& regions) |
221 | +{ |
222 | + confine_function = [regions, this](mir::geometry::Point& pos) |
223 | + { |
224 | + input_region->confine(pos); |
225 | + regions.confine(pos); |
226 | + }; |
227 | +} |
228 | + |
229 | +void mi::SeatInputDeviceTracker::reset_confinement_regions() |
230 | +{ |
231 | + confine_function = [this](mir::geometry::Point& pos) { input_region->confine(pos); }; |
232 | +} |
233 | + |
234 | +void mi::SeatInputDeviceTracker::confine_pointer() |
235 | +{ |
236 | mir::geometry::Point const old{cursor_x, cursor_y}; |
237 | auto confined = old; |
238 | - input_region->confine(confined); |
239 | + confine_function(confined); |
240 | if (confined.x != old.x) cursor_x = confined.x.as_int(); |
241 | if (confined.y != old.y) cursor_y = confined.y.as_int(); |
242 | +} |
243 | + |
244 | +void mi::SeatInputDeviceTracker::update_cursor(MirPointerEvent const* event) |
245 | +{ |
246 | + cursor_x += mir_pointer_event_axis_value(event, mir_pointer_axis_relative_x); |
247 | + cursor_y += mir_pointer_event_axis_value(event, mir_pointer_axis_relative_y); |
248 | + |
249 | + confine_pointer(); |
250 | |
251 | cursor_listener->cursor_moved_to(cursor_x, cursor_y); |
252 | } |
253 | |
254 | === modified file 'src/server/input/seat_input_device_tracker.h' |
255 | --- src/server/input/seat_input_device_tracker.h 2016-05-03 06:55:25 +0000 |
256 | +++ src/server/input/seat_input_device_tracker.h 2016-06-27 20:45:54 +0000 |
257 | @@ -22,6 +22,7 @@ |
258 | |
259 | #include "mir/input/touch_visualizer.h" |
260 | #include "mir/geometry/point.h" |
261 | +#include "mir/geometry/rectangles.h" |
262 | #include "mir_toolkit/event.h" |
263 | #include <unordered_map> |
264 | #include <memory> |
265 | @@ -57,11 +58,15 @@ |
266 | geometry::Point cursor_position() const; |
267 | MirInputEventModifiers event_modifier() const; |
268 | MirInputEventModifiers event_modifier(MirInputDeviceId) const; |
269 | + |
270 | + void set_confinement_regions(geometry::Rectangles const& region); |
271 | + void reset_confinement_regions(); |
272 | private: |
273 | void update_seat_properties(MirInputEvent const* event); |
274 | void update_cursor(MirPointerEvent const* event); |
275 | void update_spots(); |
276 | void update_states(); |
277 | + void confine_pointer(); |
278 | |
279 | std::shared_ptr<InputDispatcher> const dispatcher; |
280 | std::shared_ptr<TouchVisualizer> const touch_visualizer; |
281 | @@ -88,6 +93,7 @@ |
282 | MirPointerButtons buttons; |
283 | std::unordered_map<MirInputDeviceId, DeviceData> device_data; |
284 | std::vector<TouchVisualizer::Spot> spots; |
285 | + std::function<void(mir::geometry::Point&)> confine_function; |
286 | }; |
287 | |
288 | } |
289 | |
290 | === modified file 'src/server/scene/basic_surface.cpp' |
291 | --- src/server/scene/basic_surface.cpp 2016-05-03 06:55:25 +0000 |
292 | +++ src/server/scene/basic_surface.cpp 2016-06-27 20:45:54 +0000 |
293 | @@ -217,6 +217,7 @@ |
294 | std::string const& name, |
295 | geometry::Rectangle rect, |
296 | std::weak_ptr<Surface> const& parent, |
297 | + MirPointerConfinementState state, |
298 | bool nonrectangular, |
299 | std::list<StreamInfo> const& layers, |
300 | std::shared_ptr<mi::InputChannel> const& input_channel, |
301 | @@ -237,6 +238,7 @@ |
302 | report(report), |
303 | parent_(parent), |
304 | layers(layers), |
305 | + confine_pointer_state_(state), |
306 | cursor_stream_adapter{std::make_unique<ms::CursorStreamImageAdapter>(*this)}, |
307 | input_validator([this](MirEvent const& ev) { this->input_sender->send_event(ev, server_input_channel); }) |
308 | { |
309 | @@ -246,13 +248,14 @@ |
310 | ms::BasicSurface::BasicSurface( |
311 | std::string const& name, |
312 | geometry::Rectangle rect, |
313 | + MirPointerConfinementState state, |
314 | bool nonrectangular, |
315 | std::list<StreamInfo> const& layers, |
316 | std::shared_ptr<mi::InputChannel> const& input_channel, |
317 | std::shared_ptr<input::InputSender> const& input_sender, |
318 | std::shared_ptr<mg::CursorImage> const& cursor_image, |
319 | std::shared_ptr<SceneReport> const& report) : |
320 | - BasicSurface(name, rect, std::shared_ptr<Surface>{nullptr}, nonrectangular, layers, |
321 | + BasicSurface(name, rect, std::shared_ptr<Surface>{nullptr}, state, nonrectangular, layers, |
322 | input_channel, input_sender, cursor_image, report) |
323 | { |
324 | } |
325 | @@ -916,3 +919,13 @@ |
326 | } |
327 | return list; |
328 | } |
329 | + |
330 | +void ms::BasicSurface::set_confine_pointer_state(MirPointerConfinementState state) |
331 | +{ |
332 | + confine_pointer_state_ = state; |
333 | +} |
334 | + |
335 | +MirPointerConfinementState ms::BasicSurface::confine_pointer_state() const |
336 | +{ |
337 | + return confine_pointer_state_; |
338 | +} |
339 | |
340 | === modified file 'src/server/scene/basic_surface.h' |
341 | --- src/server/scene/basic_surface.h 2016-04-19 06:29:53 +0000 |
342 | +++ src/server/scene/basic_surface.h 2016-06-27 20:45:54 +0000 |
343 | @@ -64,6 +64,7 @@ |
344 | BasicSurface( |
345 | std::string const& name, |
346 | geometry::Rectangle rect, |
347 | + MirPointerConfinementState state, |
348 | bool nonrectangular, |
349 | std::list<scene::StreamInfo> const& streams, |
350 | std::shared_ptr<input::InputChannel> const& input_channel, |
351 | @@ -75,6 +76,7 @@ |
352 | std::string const& name, |
353 | geometry::Rectangle rect, |
354 | std::weak_ptr<Surface> const& parent, |
355 | + MirPointerConfinementState state, |
356 | bool nonrectangular, |
357 | std::list<scene::StreamInfo> const& streams, |
358 | std::shared_ptr<input::InputChannel> const& input_channel, |
359 | @@ -148,6 +150,9 @@ |
360 | |
361 | void rename(std::string const& title) override; |
362 | |
363 | + void set_confine_pointer_state(MirPointerConfinementState state) override; |
364 | + MirPointerConfinementState confine_pointer_state() const override; |
365 | + |
366 | private: |
367 | bool visible(std::unique_lock<std::mutex>&) const; |
368 | MirSurfaceType set_type(MirSurfaceType t); // Use configure() to make public changes |
369 | @@ -184,6 +189,7 @@ |
370 | int dpi_ = 0; |
371 | MirSurfaceVisibility visibility_ = mir_surface_visibility_occluded; |
372 | MirOrientationMode pref_orientation_mode = mir_orientation_mode_any; |
373 | + MirPointerConfinementState confine_pointer_state_ = mir_pointer_unconfined; |
374 | |
375 | std::unique_ptr<CursorStreamImageAdapter> const cursor_stream_adapter; |
376 | |
377 | |
378 | === modified file 'src/server/scene/surface_allocator.cpp' |
379 | --- src/server/scene/surface_allocator.cpp 2016-04-19 06:29:53 +0000 |
380 | +++ src/server/scene/surface_allocator.cpp 2016-06-27 20:45:54 +0000 |
381 | @@ -53,10 +53,12 @@ |
382 | { |
383 | bool nonrectangular = has_alpha(params.pixel_format); |
384 | auto input_channel = input_factory->make_input_channel(); |
385 | + auto confine = params.confine_pointer.is_set() ? params.confine_pointer.value() : mir_pointer_unconfined; |
386 | auto const surface = std::make_shared<BasicSurface>( |
387 | params.name, |
388 | geom::Rectangle{params.top_left, params.size}, |
389 | params.parent, |
390 | + confine, |
391 | nonrectangular, |
392 | streams, |
393 | input_channel, |
394 | |
395 | === modified file 'src/server/shell/abstract_shell.cpp' |
396 | --- src/server/shell/abstract_shell.cpp 2016-01-29 08:18:22 +0000 |
397 | +++ src/server/shell/abstract_shell.cpp 2016-06-27 20:45:54 +0000 |
398 | @@ -27,9 +27,11 @@ |
399 | #include "mir/scene/session_coordinator.h" |
400 | #include "mir/scene/session.h" |
401 | #include "mir/scene/surface.h" |
402 | +#include "mir/input/seat.h" |
403 | |
404 | namespace mf = mir::frontend; |
405 | namespace ms = mir::scene; |
406 | +namespace mi = mir::input; |
407 | namespace msh = mir::shell; |
408 | |
409 | msh::AbstractShell::AbstractShell( |
410 | @@ -38,12 +40,14 @@ |
411 | std::shared_ptr<ms::SessionCoordinator> const& session_coordinator, |
412 | std::shared_ptr<ms::PromptSessionManager> const& prompt_session_manager, |
413 | std::shared_ptr<ShellReport> const& report, |
414 | - std::function<std::shared_ptr<shell::WindowManager>(FocusController* focus_controller)> const& wm_builder) : |
415 | + std::function<std::shared_ptr<shell::WindowManager>(FocusController* focus_controller)> const& wm_builder, |
416 | + std::shared_ptr<mi::Seat> const& seat) : |
417 | input_targeter(input_targeter), |
418 | surface_stack(surface_stack), |
419 | session_coordinator(session_coordinator), |
420 | prompt_session_manager(prompt_session_manager), |
421 | window_manager(wm_builder(this)), |
422 | + seat(seat), |
423 | report(report) |
424 | { |
425 | } |
426 | @@ -113,6 +117,18 @@ |
427 | { |
428 | window_manager->modify_surface(session, surface, wm_relevant_mods); |
429 | } |
430 | + |
431 | + if (modifications.confine_pointer.is_set()) |
432 | + { |
433 | + if (surface->confine_pointer_state() == mir_pointer_confined_to_surface) |
434 | + { |
435 | + seat->set_confinement_regions({surface->input_bounds()}); |
436 | + } |
437 | + else |
438 | + { |
439 | + seat->reset_confinement_regions(); |
440 | + } |
441 | + } |
442 | } |
443 | |
444 | void msh::AbstractShell::destroy_surface( |
445 | @@ -224,12 +240,18 @@ |
446 | if (surface != current_focus) |
447 | { |
448 | focus_surface = surface; |
449 | + seat->reset_confinement_regions(); |
450 | |
451 | if (current_focus) |
452 | current_focus->configure(mir_surface_attrib_focus, mir_surface_unfocused); |
453 | |
454 | if (surface) |
455 | { |
456 | + if (surface->confine_pointer_state() == mir_pointer_confined_to_surface) |
457 | + { |
458 | + seat->set_confinement_regions({surface->input_bounds()}); |
459 | + } |
460 | + |
461 | // Ensure the surface has really taken the focus before notifying it that it is focused |
462 | input_targeter->set_focus(surface); |
463 | surface->configure(mir_surface_attrib_focus, mir_surface_focused); |
464 | |
465 | === modified file 'src/server/shell/canonical_window_manager.cpp' |
466 | --- src/server/shell/canonical_window_manager.cpp 2016-06-22 14:52:57 +0000 |
467 | +++ src/server/shell/canonical_window_manager.cpp 2016-06-27 20:45:54 +0000 |
468 | @@ -408,6 +408,11 @@ |
469 | auto const state = handle_set_state(surface, modifications.state.value()); |
470 | surface->configure(mir_surface_attrib_state, state); |
471 | } |
472 | + |
473 | + if (modifications.confine_pointer.is_set()) |
474 | + { |
475 | + surface->set_confine_pointer_state(modifications.confine_pointer.value()); |
476 | + } |
477 | } |
478 | |
479 | void msh::CanonicalWindowManagerPolicy::handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface) |
480 | |
481 | === modified file 'src/server/shell/default_configuration.cpp' |
482 | --- src/server/shell/default_configuration.cpp 2016-06-09 19:29:52 +0000 |
483 | +++ src/server/shell/default_configuration.cpp 2016-06-27 20:45:54 +0000 |
484 | @@ -41,7 +41,8 @@ |
485 | the_session_coordinator(), |
486 | the_prompt_session_manager(), |
487 | the_shell_report(), |
488 | - the_window_manager_builder())); |
489 | + the_window_manager_builder(), |
490 | + the_seat())); |
491 | |
492 | the_composite_event_filter()->prepend(result); |
493 | |
494 | |
495 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
496 | --- tests/acceptance-tests/CMakeLists.txt 2016-06-09 22:54:09 +0000 |
497 | +++ tests/acceptance-tests/CMakeLists.txt 2016-06-27 20:45:54 +0000 |
498 | @@ -19,6 +19,7 @@ |
499 | test_client_surface_events.cpp |
500 | test_client_surface_swap_buffers.cpp |
501 | test_command_line_handling.cpp |
502 | + test_confined_pointer.cpp |
503 | test_client_surfaces.cpp |
504 | test_client_logging.cpp |
505 | test_custom_window_management.cpp |
506 | |
507 | === added file 'tests/acceptance-tests/test_confined_pointer.cpp' |
508 | --- tests/acceptance-tests/test_confined_pointer.cpp 1970-01-01 00:00:00 +0000 |
509 | +++ tests/acceptance-tests/test_confined_pointer.cpp 2016-06-27 20:45:54 +0000 |
510 | @@ -0,0 +1,214 @@ |
511 | +/* |
512 | + * Copyright © 2016 Canonical Ltd. |
513 | + * |
514 | + * This program is free software: you can redistribute it and/or modify |
515 | + * it under the terms of the GNU General Public License version 3 as |
516 | + * published by the Free Software Foundation. |
517 | + * |
518 | + * This program is distributed in the hope that it will be useful, |
519 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
520 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
521 | + * GNU General Public License for more details. |
522 | + * |
523 | + * You should have received a copy of the GNU General Public License |
524 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
525 | + * |
526 | + * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com> |
527 | + */ |
528 | + |
529 | +#include "mir/test/event_matchers.h" |
530 | +#include "mir/input/input_device_info.h" |
531 | +#include "mir_test_framework/fake_input_device.h" |
532 | +#include "mir_test_framework/stub_server_platform_factory.h" |
533 | + |
534 | +#include "mir/test/signal.h" |
535 | +#include "mir_test_framework/placement_applying_shell.h" |
536 | +#include "mir_test_framework/headless_in_process_server.h" |
537 | + |
538 | +#include "mir_toolkit/mir_client_library.h" |
539 | + |
540 | +#include <gtest/gtest.h> |
541 | +#include <gmock/gmock.h> |
542 | + |
543 | +#include <boost/throw_exception.hpp> |
544 | + |
545 | + |
546 | +namespace mt = mir::test; |
547 | +namespace mi = mir::input; |
548 | +namespace mis = mir::input::synthesis; |
549 | +namespace mtf = mir_test_framework; |
550 | +namespace geom = mir::geometry; |
551 | + |
552 | +using namespace std::chrono_literals; |
553 | + |
554 | +namespace |
555 | +{ |
556 | +int const surface_width = 100; |
557 | +int const surface_height = 100; |
558 | +} |
559 | + |
560 | +void null_event_handler(MirSurface*, MirEvent const*, void*) |
561 | +{ |
562 | +} |
563 | + |
564 | +struct Client |
565 | +{ |
566 | + MirSurface* surface{nullptr}; |
567 | + |
568 | + MOCK_METHOD1(handle_input, void(MirEvent const*)); |
569 | + |
570 | + Client(std::string const& con, std::string const& name) |
571 | + { |
572 | + connection = mir_connect_sync(con.c_str(), name.c_str()); |
573 | + |
574 | + if (!mir_connection_is_valid(connection)) |
575 | + { |
576 | + BOOST_THROW_EXCEPTION( |
577 | + std::runtime_error{std::string{"Failed to connect to test server: "} + |
578 | + mir_connection_get_error_message(connection)}); |
579 | + } |
580 | + auto spec = mir_connection_create_spec_for_normal_surface(connection, surface_width, |
581 | + surface_height, mir_pixel_format_abgr_8888); |
582 | + mir_surface_spec_set_pointer_confinement(spec, mir_pointer_confined_to_surface); |
583 | + mir_surface_spec_set_name(spec, name.c_str()); |
584 | + surface = mir_surface_create_sync(spec); |
585 | + mir_surface_spec_release(spec); |
586 | + if (!mir_surface_is_valid(surface)) |
587 | + { |
588 | + BOOST_THROW_EXCEPTION(std::runtime_error{std::string{"Failed creating a surface: "}+ |
589 | + mir_surface_get_error_message(surface)}); |
590 | + } |
591 | + |
592 | + mir_surface_set_event_handler(surface, handle_event, this); |
593 | + mir_buffer_stream_swap_buffers_sync( |
594 | + mir_surface_get_buffer_stream(surface)); |
595 | + |
596 | + ready_to_accept_events.wait_for(4s); |
597 | + if (!ready_to_accept_events.raised()) |
598 | + { |
599 | + BOOST_THROW_EXCEPTION(std::runtime_error("Timeout waiting for surface to become focused and exposed")); |
600 | + } |
601 | + } |
602 | + |
603 | + void handle_surface_event(MirSurfaceEvent const* event) |
604 | + { |
605 | + auto const attrib = mir_surface_event_get_attribute(event); |
606 | + auto const value = mir_surface_event_get_attribute_value(event); |
607 | + |
608 | + if (mir_surface_attrib_visibility == attrib && |
609 | + mir_surface_visibility_exposed == value) |
610 | + exposed = true; |
611 | + |
612 | + if (mir_surface_attrib_focus == attrib && |
613 | + mir_surface_focused == value) |
614 | + focused = true; |
615 | + |
616 | + if (exposed && focused) |
617 | + ready_to_accept_events.raise(); |
618 | + } |
619 | + |
620 | + static void handle_event(MirSurface*, MirEvent const* ev, void* context) |
621 | + { |
622 | + auto const client = static_cast<Client*>(context); |
623 | + auto type = mir_event_get_type(ev); |
624 | + if (type == mir_event_type_surface) |
625 | + { |
626 | + auto surface_event = mir_event_get_surface_event(ev); |
627 | + client->handle_surface_event(surface_event); |
628 | + |
629 | + } |
630 | + if (type == mir_event_type_input) |
631 | + { |
632 | + client->handle_input(ev); |
633 | + } |
634 | + } |
635 | + ~Client() |
636 | + { |
637 | + // Remove the event handler to avoid handling spurious events unrelated |
638 | + // to the tests (e.g. pointer leave events when the surface is destroyed), |
639 | + // which can cause test expectations to fail. |
640 | + mir_surface_set_event_handler(surface, null_event_handler, nullptr); |
641 | + mir_surface_release_sync(surface); |
642 | + mir_connection_release(connection); |
643 | + } |
644 | + |
645 | + MirConnection* connection; |
646 | + mir::test::Signal ready_to_accept_events; |
647 | + mir::test::Signal all_events_received; |
648 | + bool exposed = false; |
649 | + bool focused = false; |
650 | +}; |
651 | + |
652 | +struct PointerConfinement : mtf::HeadlessInProcessServer |
653 | +{ |
654 | + void SetUp() override |
655 | + { |
656 | + initial_display_layout({screen_geometry}); |
657 | + |
658 | + server.wrap_shell( |
659 | + [this](std::shared_ptr<mir::shell::Shell> const& wrapped) |
660 | + { |
661 | + //return wrapped; |
662 | + shell = std::make_shared<mtf::PlacementApplyingShell>(wrapped, input_regions, positions); |
663 | + return shell; |
664 | + }); |
665 | + |
666 | + HeadlessInProcessServer::SetUp(); |
667 | + |
668 | + positions[first] = geom::Rectangle{{0,0}, {surface_width, surface_height}}; |
669 | + } |
670 | + |
671 | + std::string const mouse_name = "mouse"; |
672 | + std::string const mouse_unique_id = "mouse-uid"; |
673 | + std::unique_ptr<mtf::FakeInputDevice> fake_mouse{ |
674 | + mtf::add_fake_input_device(mi::InputDeviceInfo{mouse_name, mouse_unique_id, mi::DeviceCapability::pointer})}; |
675 | + |
676 | + std::shared_ptr<mtf::PlacementApplyingShell> shell; |
677 | + geom::Rectangle screen_geometry{{0,0}, {800,600}}; |
678 | + mtf::ClientInputRegions input_regions; |
679 | + std::string first{"first"}; |
680 | + mtf::ClientPositions positions; |
681 | + mtf::TemporaryEnvironmentValue disable_batching{"MIR_CLIENT_INPUT_RATE", "0"}; |
682 | +}; |
683 | + |
684 | +TEST_F(PointerConfinement, test_we_hit_pointer_confined_boundary) |
685 | +{ |
686 | + using namespace ::testing; |
687 | + |
688 | + positions[first] = geom::Rectangle{{0,0}, {surface_width, surface_height}}; |
689 | + Client client(new_connection(), first); |
690 | + |
691 | + InSequence seq; |
692 | + EXPECT_CALL(client, handle_input(mt::PointerEnterEvent())); |
693 | + EXPECT_CALL(client, handle_input(mt::PointerEventWithPosition(surface_width / 2, 0))); |
694 | + EXPECT_CALL(client, handle_input(AllOf(mt::PointerEventWithPosition(surface_width - 1, 0), |
695 | + mt::PointerEventWithDiff(surface_width * 2, 0)))); |
696 | + EXPECT_CALL(client, handle_input(AllOf(mt::PointerEventWithPosition(surface_width - 1, 0), |
697 | + mt::PointerEventWithDiff(10, 0)))) |
698 | + .WillOnce(mt::WakeUp(&client.all_events_received)); |
699 | + |
700 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(surface_width / 2, 0)); |
701 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(surface_width * 2, 0)); |
702 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(10, 0)); |
703 | + |
704 | + client.all_events_received.wait_for(10s); |
705 | +} |
706 | + |
707 | +TEST_F(PointerConfinement, test_we_generate_relative_after_boundary) |
708 | +{ |
709 | + using namespace ::testing; |
710 | + |
711 | + positions[first] = geom::Rectangle{{0,0}, {surface_width, surface_height}}; |
712 | + Client client(new_connection(), first); |
713 | + |
714 | + InSequence seq; |
715 | + EXPECT_CALL(client, handle_input(mt::PointerEnterEvent())); |
716 | + EXPECT_CALL(client, handle_input(mt::PointerEventWithPosition(surface_width - 1, 0))); |
717 | + EXPECT_CALL(client, handle_input(AllOf(mt::PointerEventWithPosition(surface_width - 1, 0), mt::PointerEventWithDiff(10, 0)))) |
718 | + .WillOnce(mt::WakeUp(&client.all_events_received)); |
719 | + |
720 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(surface_width + 1, 0)); |
721 | + fake_mouse->emit_event(mis::a_pointer_event().with_movement(10, 0)); |
722 | + |
723 | + client.all_events_received.wait_for(10s); |
724 | +} |
725 | |
726 | === modified file 'tests/acceptance-tests/test_surface_placement.cpp' |
727 | --- tests/acceptance-tests/test_surface_placement.cpp 2016-04-18 09:29:26 +0000 |
728 | +++ tests/acceptance-tests/test_surface_placement.cpp 2016-06-27 20:45:54 +0000 |
729 | @@ -19,6 +19,7 @@ |
730 | #include "mir/events/event_builders.h" |
731 | #include "mir/scene/surface.h" |
732 | |
733 | +#include "mir_test_framework/temporary_environment_value.h" |
734 | #include "mir/test/doubles/wrap_shell_to_track_latest_surface.h" |
735 | #include "mir_test_framework/connected_client_headless_server.h" |
736 | #include "mir/test/fake_shared.h" |
737 | |
738 | === modified file 'tests/include/mir/test/doubles/mock_input_seat.h' |
739 | --- tests/include/mir/test/doubles/mock_input_seat.h 2016-05-03 06:55:25 +0000 |
740 | +++ tests/include/mir/test/doubles/mock_input_seat.h 2016-06-27 20:45:54 +0000 |
741 | @@ -22,6 +22,7 @@ |
742 | #include "mir/input/seat.h" |
743 | |
744 | #include <gmock/gmock.h> |
745 | +#include "mir/input/device.h" |
746 | |
747 | namespace mir |
748 | { |
749 | @@ -35,6 +36,8 @@ |
750 | MOCK_METHOD1(remove_device, void(input::Device const& device)); |
751 | MOCK_METHOD1(dispatch_event, void(MirEvent& event)); |
752 | MOCK_METHOD1(get_rectangle_for, geometry::Rectangle(input::Device const& dev)); |
753 | + MOCK_METHOD1(set_confinement_regions, void(geometry::Rectangles const&)); |
754 | + MOCK_METHOD0(reset_confinement_regions, void()); |
755 | }; |
756 | } |
757 | } |
758 | |
759 | === modified file 'tests/include/mir/test/doubles/mock_surface.h' |
760 | --- tests/include/mir/test/doubles/mock_surface.h 2016-04-19 06:29:53 +0000 |
761 | +++ tests/include/mir/test/doubles/mock_surface.h 2016-06-27 20:45:54 +0000 |
762 | @@ -42,6 +42,7 @@ |
763 | scene::BasicSurface( |
764 | {}, |
765 | {{},{}}, |
766 | + mir_pointer_unconfined, |
767 | true, |
768 | { { std::make_shared<testing::NiceMock<MockBufferStream>>(), {0, 0}, {} } }, |
769 | std::make_shared<StubInputChannel>(), |
770 | |
771 | === modified file 'tests/include/mir/test/doubles/stub_scene_surface.h' |
772 | --- tests/include/mir/test/doubles/stub_scene_surface.h 2016-01-29 08:18:22 +0000 |
773 | +++ tests/include/mir/test/doubles/stub_scene_surface.h 2016-06-27 20:45:54 +0000 |
774 | @@ -105,6 +105,9 @@ |
775 | void set_cursor_stream(std::shared_ptr<frontend::BufferStream> const&, geometry::Displacement const&) {} |
776 | void rename(std::string const&) {} |
777 | std::shared_ptr<frontend::BufferStream> primary_buffer_stream() const override { return nullptr; } |
778 | + |
779 | + void set_confine_pointer_state(MirPointerConfinementState /*state*/) override {} |
780 | + MirPointerConfinementState confine_pointer_state() const override { return {}; } |
781 | }; |
782 | |
783 | } |
784 | |
785 | === modified file 'tests/integration-tests/surface_composition.cpp' |
786 | --- tests/integration-tests/surface_composition.cpp 2016-04-19 06:29:53 +0000 |
787 | +++ tests/integration-tests/surface_composition.cpp 2016-06-27 20:45:54 +0000 |
788 | @@ -48,6 +48,7 @@ |
789 | return std::make_shared<ms::BasicSurface>( |
790 | std::string("SurfaceComposition"), |
791 | geom::Rectangle{{},{}}, |
792 | + mir_pointer_unconfined, |
793 | false, |
794 | std::list<ms::StreamInfo> { { stream, {0,0}, {} } }, |
795 | create_input_channel(), |
796 | |
797 | === modified file 'tests/integration-tests/test_surface_stack_with_compositor.cpp' |
798 | --- tests/integration-tests/test_surface_stack_with_compositor.cpp 2016-04-19 06:29:53 +0000 |
799 | +++ tests/integration-tests/test_surface_stack_with_compositor.cpp 2016-06-27 20:45:54 +0000 |
800 | @@ -127,6 +127,7 @@ |
801 | stub_surface{std::make_shared<ms::BasicSurface>( |
802 | std::string("stub"), |
803 | geom::Rectangle{{0,0},{1,1}}, |
804 | + mir_pointer_unconfined, |
805 | false, |
806 | streams, |
807 | std::shared_ptr<mir::input::InputChannel>(), |
808 | |
809 | === modified file 'tests/mir_test_framework/stub_surface.cpp' |
810 | --- tests/mir_test_framework/stub_surface.cpp 2016-01-29 08:18:22 +0000 |
811 | +++ tests/mir_test_framework/stub_surface.cpp 2016-06-27 20:45:54 +0000 |
812 | @@ -200,6 +200,16 @@ |
813 | { |
814 | } |
815 | |
816 | +void mtd::StubSurface::set_confine_pointer_state(MirPointerConfinementState /*state*/) |
817 | +{ |
818 | +} |
819 | + |
820 | +MirPointerConfinementState mtd::StubSurface::confine_pointer_state() const |
821 | +{ |
822 | + return {}; |
823 | +} |
824 | + |
825 | + |
826 | namespace |
827 | { |
828 | // Ensure we don't accidentally have an abstract class |
829 | |
830 | === modified file 'tests/unit-tests/input/test_seat_input_device_tracker.cpp' |
831 | --- tests/unit-tests/input/test_seat_input_device_tracker.cpp 2016-04-19 06:29:53 +0000 |
832 | +++ tests/unit-tests/input/test_seat_input_device_tracker.cpp 2016-06-27 20:45:54 +0000 |
833 | @@ -37,6 +37,7 @@ |
834 | namespace mt = mir::test; |
835 | namespace mtd = mt::doubles; |
836 | namespace mi = mir::input; |
837 | +namespace geom = mir::geometry; |
838 | namespace |
839 | { |
840 | |
841 | @@ -292,3 +293,38 @@ |
842 | tracker.dispatch(*another_device_builder.pointer_event(arbitrary_timestamp, mir_pointer_action_motion, |
843 | mir_pointer_button_secondary, 0, 0, 0, 0)); |
844 | } |
845 | + |
846 | +TEST_F(SeatInputDeviceTracker, pointer_confinement_bounds_mouse_inside) |
847 | +{ |
848 | + auto const move_x = 20.0f, move_y = 40.0f; |
849 | + auto const max_w_h = 100; |
850 | + EXPECT_CALL(mock_cursor_listener, cursor_moved_to(move_x, move_y)).Times(1); |
851 | + EXPECT_CALL(mock_cursor_listener, cursor_moved_to(max_w_h - 1, max_w_h - 1)).Times(1); |
852 | + |
853 | + geom::Rectangle rec{{0, 0}, {max_w_h, max_w_h}}; |
854 | + tracker.set_confinement_regions({rec}); |
855 | + tracker.add_device(some_device); |
856 | + tracker.dispatch(*some_device_builder.pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, |
857 | + move_x, move_y)); |
858 | + tracker.dispatch(*some_device_builder.pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, |
859 | + max_w_h * 2, max_w_h * 2)); |
860 | +} |
861 | + |
862 | +TEST_F(SeatInputDeviceTracker, reset_pointer_confinement_allows_movement_past) |
863 | +{ |
864 | + auto const move_x = 20.0f, move_y = 40.0f; |
865 | + auto const max_w_h = 100; |
866 | + EXPECT_CALL(mock_cursor_listener, cursor_moved_to(move_x, move_y)).Times(1); |
867 | + EXPECT_CALL(mock_cursor_listener, cursor_moved_to(move_x + max_w_h * 2, |
868 | + move_y + max_w_h * 2)).Times(1); |
869 | + |
870 | + geom::Rectangle rec{{0, 0}, {max_w_h, max_w_h}}; |
871 | + tracker.set_confinement_regions({rec}); |
872 | + tracker.add_device(some_device); |
873 | + tracker.dispatch(*some_device_builder.pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, |
874 | + move_x, move_y)); |
875 | + |
876 | + tracker.reset_confinement_regions(); |
877 | + tracker.dispatch(*some_device_builder.pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, |
878 | + max_w_h * 2, max_w_h * 2)); |
879 | +} |
880 | |
881 | === modified file 'tests/unit-tests/scene/test_abstract_shell.cpp' |
882 | --- tests/unit-tests/scene/test_abstract_shell.cpp 2016-05-04 01:48:16 +0000 |
883 | +++ tests/unit-tests/scene/test_abstract_shell.cpp 2016-06-27 20:45:54 +0000 |
884 | @@ -41,6 +41,7 @@ |
885 | #include "mir/test/doubles/stub_buffer_allocator.h" |
886 | #include "mir/test/doubles/null_application_not_responding_detector.h" |
887 | #include "mir/test/doubles/stub_display.h" |
888 | +#include "mir/test/doubles/mock_input_seat.h" |
889 | |
890 | #include "mir/test/fake_shared.h" |
891 | |
892 | @@ -108,6 +109,7 @@ |
893 | NiceMock<MockSessionContainer> session_container; |
894 | NiceMock<MockSessionEventSink> session_event_sink; |
895 | NiceMock<MockSurfaceFactory> surface_factory; |
896 | + NiceMock<mtd::MockInputSeat> seat; |
897 | mtd::StubDisplay display{3}; |
898 | |
899 | NiceMock<MockSessionManager> session_manager{ |
900 | @@ -131,7 +133,8 @@ |
901 | mt::fake_shared(session_manager), |
902 | std::make_shared<mtd::NullPromptSessionManager>(), |
903 | std::make_shared<mir::report::null::ShellReport>(), |
904 | - [this](msh::FocusController*) { return wm = std::make_shared<NiceMockWindowManager>(); }}; |
905 | + [this](msh::FocusController*) { return wm = std::make_shared<NiceMockWindowManager>(); }, |
906 | + mt::fake_shared(seat)}; |
907 | |
908 | void SetUp() override |
909 | { |
910 | |
911 | === modified file 'tests/unit-tests/scene/test_basic_surface.cpp' |
912 | --- tests/unit-tests/scene/test_basic_surface.cpp 2016-05-03 06:55:25 +0000 |
913 | +++ tests/unit-tests/scene/test_basic_surface.cpp 2016-06-27 20:45:54 +0000 |
914 | @@ -93,6 +93,7 @@ |
915 | ms::BasicSurface surface{ |
916 | name, |
917 | rect, |
918 | + mir_pointer_unconfined, |
919 | false, |
920 | streams, |
921 | std::shared_ptr<mi::InputChannel>(), |
922 | @@ -121,7 +122,7 @@ |
923 | for (auto& surface : surfaces) |
924 | { |
925 | surface = std::make_unique<ms::BasicSurface>( |
926 | - name, rect, false, |
927 | + name, rect, mir_pointer_unconfined, false, |
928 | std::list<ms::StreamInfo> { |
929 | { std::make_shared<testing::NiceMock<mtd::MockBufferStream>>(), {}, {} } }, |
930 | std::shared_ptr<mi::InputChannel>(), stub_input_sender, |
931 | @@ -142,7 +143,7 @@ |
932 | for (auto& surface : surfaces) |
933 | { |
934 | surface = std::make_unique<ms::BasicSurface>( |
935 | - name, rect, false, streams, |
936 | + name, rect, mir_pointer_unconfined, false, streams, |
937 | std::shared_ptr<mi::InputChannel>(), stub_input_sender, |
938 | std::shared_ptr<mg::CursorImage>(), report); |
939 | |
940 | @@ -265,6 +266,7 @@ |
941 | ms::BasicSurface surface{ |
942 | name, |
943 | rect, |
944 | + mir_pointer_unconfined, |
945 | false, |
946 | streams, |
947 | std::shared_ptr<mi::InputChannel>(), |
948 | @@ -305,6 +307,7 @@ |
949 | ms::BasicSurface surface{ |
950 | name, |
951 | geom::Rectangle{pt, one_by_one}, |
952 | + mir_pointer_unconfined, |
953 | false, |
954 | streams, |
955 | std::shared_ptr<mi::InputChannel>(), |
956 | @@ -346,6 +349,7 @@ |
957 | ms::BasicSurface surface{ |
958 | name, |
959 | geom::Rectangle{{0,0}, {100,100}}, |
960 | + mir_pointer_unconfined, |
961 | false, |
962 | streams, |
963 | std::shared_ptr<mi::InputChannel>(), |
964 | @@ -486,6 +490,7 @@ |
965 | name, |
966 | geom::Rectangle{{0,0}, {100,100}}, |
967 | parent, |
968 | + mir_pointer_unconfined, |
969 | false, |
970 | streams, |
971 | std::shared_ptr<mi::InputChannel>(), |
972 | @@ -673,6 +678,7 @@ |
973 | ms::BasicSurface surface{ |
974 | name, |
975 | rect, |
976 | + mir_pointer_unconfined, |
977 | false, |
978 | streams, |
979 | std::shared_ptr<mi::InputChannel>(), |
980 | |
981 | === modified file 'tests/unit-tests/scene/test_session_manager.cpp' |
982 | --- tests/unit-tests/scene/test_session_manager.cpp 2016-05-04 01:48:16 +0000 |
983 | +++ tests/unit-tests/scene/test_session_manager.cpp 2016-06-27 20:45:54 +0000 |
984 | @@ -83,6 +83,7 @@ |
985 | std::shared_ptr<ms::Surface> dummy_surface = std::make_shared<ms::BasicSurface>( |
986 | std::string("stub"), |
987 | geom::Rectangle{{},{}}, |
988 | + mir_pointer_unconfined, |
989 | false, |
990 | std::list<ms::StreamInfo> { { std::make_shared<mtd::StubBufferStream>(), {}, {} } }, |
991 | std::shared_ptr<mi::InputChannel>(), |
992 | |
993 | === modified file 'tests/unit-tests/scene/test_surface.cpp' |
994 | --- tests/unit-tests/scene/test_surface.cpp 2016-05-03 06:55:25 +0000 |
995 | +++ tests/unit-tests/scene/test_surface.cpp 2016-06-27 20:45:54 +0000 |
996 | @@ -193,7 +193,8 @@ |
997 | { |
998 | SurfaceCreation() |
999 | : surface(surface_name, |
1000 | - rect, false, streams, |
1001 | + rect, mir_pointer_unconfined, |
1002 | + false, streams, |
1003 | std::make_shared<mtd::StubInputChannel>(), |
1004 | std::make_shared<mtd::StubInputSender>(), |
1005 | nullptr /* cursor_image */, report) |
1006 | @@ -377,6 +378,7 @@ |
1007 | ms::BasicSurface input_surf( |
1008 | surface_name, |
1009 | rect, |
1010 | + mir_pointer_unconfined, |
1011 | false, |
1012 | streams, |
1013 | mt::fake_shared(channel), |
1014 | @@ -395,6 +397,7 @@ |
1015 | ms::BasicSurface surface( |
1016 | surface_name, |
1017 | rect, |
1018 | + mir_pointer_unconfined, |
1019 | false, |
1020 | streams, |
1021 | std::make_shared<mtd::StubInputChannel>(), |
1022 | |
1023 | === modified file 'tests/unit-tests/scene/test_surface_impl.cpp' |
1024 | --- tests/unit-tests/scene/test_surface_impl.cpp 2016-05-03 06:55:25 +0000 |
1025 | +++ tests/unit-tests/scene/test_surface_impl.cpp 2016-06-27 20:45:54 +0000 |
1026 | @@ -83,7 +83,8 @@ |
1027 | .WillByDefault(InvokeArgument<0>(nullptr)); |
1028 | |
1029 | surface = std::make_shared<ms::BasicSurface>( |
1030 | - std::string("stub"), geom::Rectangle{{},{}}, false, |
1031 | + std::string("stub"), geom::Rectangle{{},{}}, |
1032 | + mir_pointer_unconfined, false, |
1033 | std::list<ms::StreamInfo> { { buffer_stream, {}, {} } }, |
1034 | nullptr, stub_input_sender, nullptr, report); |
1035 | } |
1036 | @@ -280,6 +281,7 @@ |
1037 | ms::BasicSurface surf( |
1038 | std::string("stub"), |
1039 | geom::Rectangle{{},{}}, |
1040 | + mir_pointer_unconfined, |
1041 | false, |
1042 | std::list<ms::StreamInfo> { { buffer_stream, {}, {} } }, |
1043 | std::shared_ptr<mi::InputChannel>(), |
1044 | |
1045 | === modified file 'tests/unit-tests/scene/test_surface_stack.cpp' |
1046 | --- tests/unit-tests/scene/test_surface_stack.cpp 2016-05-03 06:55:25 +0000 |
1047 | +++ tests/unit-tests/scene/test_surface_stack.cpp 2016-06-27 20:45:54 +0000 |
1048 | @@ -127,6 +127,7 @@ |
1049 | stub_surface1 = std::make_shared<ms::BasicSurface>( |
1050 | std::string("stub"), |
1051 | geom::Rectangle{{},{}}, |
1052 | + mir_pointer_unconfined, |
1053 | false, |
1054 | std::list<ms::StreamInfo> { { stub_buffer_stream1, {}, {} } }, |
1055 | std::shared_ptr<mir::input::InputChannel>(), |
1056 | @@ -137,6 +138,7 @@ |
1057 | stub_surface2 = std::make_shared<ms::BasicSurface>( |
1058 | std::string("stub"), |
1059 | geom::Rectangle{{},{}}, |
1060 | + mir_pointer_unconfined, |
1061 | false, |
1062 | std::list<ms::StreamInfo> { { stub_buffer_stream2, {}, {} } }, |
1063 | std::shared_ptr<mir::input::InputChannel>(), |
1064 | @@ -148,6 +150,7 @@ |
1065 | stub_surface3 = std::make_shared<ms::BasicSurface>( |
1066 | std::string("stub"), |
1067 | geom::Rectangle{{},{}}, |
1068 | + mir_pointer_unconfined, |
1069 | false, |
1070 | std::list<ms::StreamInfo> { { stub_buffer_stream3, {}, {} } }, |
1071 | std::shared_ptr<mir::input::InputChannel>(), |
1072 | @@ -159,6 +162,7 @@ |
1073 | invisible_stub_surface = std::make_shared<ms::BasicSurface>( |
1074 | std::string("stub"), |
1075 | geom::Rectangle{{},{}}, |
1076 | + mir_pointer_unconfined, |
1077 | false, |
1078 | std::list<ms::StreamInfo> { { std::make_shared<mtd::StubBufferStream>(), {}, {} } }, |
1079 | std::shared_ptr<mir::input::InputChannel>(), |
1080 | @@ -274,6 +278,7 @@ |
1081 | auto surface = std::make_shared<ms::BasicSurface>( |
1082 | std::string("Mary had a little lamb"), |
1083 | geom::Rectangle{{},{}}, |
1084 | + mir_pointer_unconfined, |
1085 | false, |
1086 | std::list<ms::StreamInfo> { { std::make_shared<mtd::StubBufferStream>(), {}, {} } }, |
1087 | std::shared_ptr<mir::input::InputChannel>(), |
1088 | @@ -303,6 +308,7 @@ |
1089 | auto surface = std::make_shared<ms::BasicSurface>( |
1090 | std::string("username@hostname: /"), |
1091 | geom::Rectangle{{},{}}, |
1092 | + mir_pointer_unconfined, |
1093 | false, |
1094 | std::list<ms::StreamInfo> { { std::make_shared<mtd::StubBufferStream>(), {}, {} } }, |
1095 | std::shared_ptr<mir::input::InputChannel>(), |
1096 | @@ -346,6 +352,7 @@ |
1097 | auto surface = std::make_shared<ms::BasicSurface>( |
1098 | std::string("stub"), |
1099 | geom::Rectangle{{},{}}, |
1100 | + mir_pointer_unconfined, |
1101 | false, |
1102 | std::list<ms::StreamInfo> { { stream, {}, {} } }, |
1103 | std::shared_ptr<mir::input::InputChannel>(), |
1104 | @@ -383,6 +390,7 @@ |
1105 | auto surface = std::make_shared<ms::BasicSurface>( |
1106 | std::string("stub"), |
1107 | geom::Rectangle{{},{}}, |
1108 | + mir_pointer_unconfined, |
1109 | false, |
1110 | std::list<ms::StreamInfo> { { stream, {}, {} } }, |
1111 | std::shared_ptr<mir::input::InputChannel>(), |
1112 | @@ -417,6 +425,7 @@ |
1113 | auto surface = std::make_shared<ms::BasicSurface>( |
1114 | std::string("stub"), |
1115 | geom::Rectangle{{},{}}, |
1116 | + mir_pointer_unconfined, |
1117 | false, |
1118 | std::list<ms::StreamInfo> { { stream, {}, {} } }, |
1119 | std::shared_ptr<mir::input::InputChannel>(), |
1120 | @@ -531,6 +540,7 @@ |
1121 | auto const surface = std::make_shared<ms::BasicSurface>( |
1122 | std::string("stub"), |
1123 | geom::Rectangle{geom::Point{3 * i, 4 * i},geom::Size{1 * i, 2 * i}}, |
1124 | + mir_pointer_unconfined, |
1125 | true, |
1126 | std::list<ms::StreamInfo> { { std::make_shared<mtd::StubBufferStream>(), {}, {} } }, |
1127 | std::shared_ptr<mir::input::InputChannel>(), |
1128 | @@ -716,6 +726,7 @@ |
1129 | auto const surface = std::make_shared<ms::BasicSurface>( |
1130 | std::string("stub"), |
1131 | geom::Rectangle{geom::Point{3 * i, 4 * i},geom::Size{1 * i, 2 * i}}, |
1132 | + mir_pointer_unconfined, |
1133 | true, |
1134 | std::list<ms::StreamInfo> { { std::make_shared<mtd::StubBufferStream>(), {}, {} } }, |
1135 | std::shared_ptr<mir::input::InputChannel>(), |
1136 | @@ -749,6 +760,7 @@ |
1137 | auto const surface = std::make_shared<ms::BasicSurface>( |
1138 | std::string("stub"), |
1139 | geom::Rectangle{geom::Point{3, 4},geom::Size{1, 2}}, |
1140 | + mir_pointer_unconfined, |
1141 | true, |
1142 | std::list<ms::StreamInfo> { { mock_stream, {}, {} } }, |
1143 | std::shared_ptr<mir::input::InputChannel>(), |
1144 | @@ -779,6 +791,7 @@ |
1145 | auto const surface = std::make_shared<ms::BasicSurface>( |
1146 | std::string("stub"), |
1147 | geom::Rectangle{geom::Point{3, 4},geom::Size{1, 2}}, |
1148 | + mir_pointer_unconfined, |
1149 | true, |
1150 | std::list<ms::StreamInfo> { { mock_stream, {}, {} } }, |
1151 | std::shared_ptr<mir::input::InputChannel>(), |
1152 | @@ -802,6 +815,7 @@ |
1153 | ms::BasicSurface( |
1154 | {}, |
1155 | {{},{}}, |
1156 | + mir_pointer_unconfined, |
1157 | true, |
1158 | std::list<ms::StreamInfo> { { std::make_shared<mtd::StubBufferStream>(), {}, {} } }, |
1159 | {}, |
PASSED: Continuous integration, rev:3537 /mir-jenkins. ubuntu. com/job/ mir-ci/ 1167/ /mir-jenkins. ubuntu. com/job/ build-mir/ 1314 /mir-jenkins. ubuntu. com/job/ build-0- fetch/1365 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 1356 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 1356 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 1326 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 1326/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 1326 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 1326/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 1326 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 1326/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 1326 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 1326/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 1326 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 1326/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
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:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 1167/rebuild
https:/