Mir

Merge lp:~andreas-pokorny/mir/combine-modifier-state-accross-devices into lp:mir

Proposed by Andreas Pokorny
Status: Merged
Merged at revision: 3065
Proposed branch: lp:~andreas-pokorny/mir/combine-modifier-state-accross-devices
Merge into: lp:mir
Prerequisite: lp:~andreas-pokorny/mir/bump-input-platform-abi-for-0.18
Diff against target: 1512 lines (+615/-265)
24 files modified
include/client/mir/events/event_builders.h (+2/-0)
include/platform/mir/input/event_builder.h (+5/-7)
include/test/mir/test/event_matchers.h (+8/-0)
src/client/events/event_builders.cpp (+22/-0)
src/client/symbols.map (+8/-0)
src/platforms/evdev/CMakeLists.txt (+2/-3)
src/platforms/evdev/button_utils.cpp (+44/-0)
src/platforms/evdev/button_utils.h (+36/-0)
src/platforms/evdev/libinput_device.cpp (+12/-34)
src/platforms/evdev/libinput_device.h (+0/-1)
src/platforms/mesa/server/x11/input/input_platform.cpp (+6/-38)
src/server/input/CMakeLists.txt (+2/-0)
src/server/input/default_event_builder.cpp (+12/-14)
src/server/input/default_event_builder.h (+5/-7)
src/server/input/default_input_device_hub.cpp (+26/-58)
src/server/input/default_input_device_hub.h (+6/-10)
src/server/input/input_modifier_utils.cpp (+4/-22)
src/server/input/input_modifier_utils.h (+2/-7)
src/server/input/seat.cpp (+161/-0)
src/server/input/seat.h (+74/-0)
tests/mir_test_framework/fake_input_device_impl.cpp (+4/-16)
tests/mir_test_framework/fake_input_device_impl.h (+0/-1)
tests/unit-tests/input/evdev/test_libinput_device.cpp (+28/-33)
tests/unit-tests/input/test_default_input_device_hub.cpp (+146/-14)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/combine-modifier-state-accross-devices
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Chris Halse Rogers Approve
Alan Griffiths Abstain
Review via email: mp+274412@code.launchpad.net

This proposal supersedes a proposal from 2015-10-14.

Commit message

Rework Modifier tracking to combine modifiers within

The platform is no longer in charge of the modifier. Instead the new input stack tracks it when the events are received. To reduce the complexity of InputDeviceHub this behavior and similar parts are moved to mir::input::Seat which represents a group of input devices that belong to a user session. (Currently all of them).

Collateral changes:
- allow changing the modifier of MirEvent after creation -> additional symbols to 'hidden' C++ client API
- reduction of EventBuilder interface
- moving of modifier utils to server

Description of the change

This fixes the problem that caused the revert of the input platform probing mp..

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

+MIR_CLIENT_DETAIL_v0.18.0 {

AIUI this should be MIR_CLIENT_DETAIL_unreleased? (and then become MIR_CLIENT_DETAIL_0.18)

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

I think this is OK, but not yet checked fully

review: Abstain
Revision history for this message
Chris Halse Rogers (raof) wrote :

Hm. The addition of Seat is great, but it looks like this will remove the ability to do per-keyboard modifiers? This isn't super-useful for things like <alt> or <ctrl>, but it's super-annoying for things like <num lock>.

Would it be possible to add the Seat interface, but still have keyboard devices handle their own modifiers? My understanding of the problem suggests that it is, but you've undoubtedly got a better understanding :)

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

> Hm. The addition of Seat is great, but it looks like this will remove the
> ability to do per-keyboard modifiers? This isn't super-useful for things like
> <alt> or <ctrl>, but it's super-annoying for things like <num lock>.
>
> Would it be possible to add the Seat interface, but still have keyboard
> devices handle their own modifiers? My understanding of the problem suggests
> that it is, but you've undoubtedly got a better understanding :)

I think we can achieve that in several ways.. and I think one of the options to do that looks robust: Have an additional keyboard device modifier property in MirEvent for keyboard events. The modifier which is currently stored per device in seat. After peeking into xkb_mapper. On the client side we would have to track the xkb state per keyboard device, and on every key event from a device inject potentially not experienced scan codes for caps lock and num lock (because it might have happened before the surface existed or when it was not focused) to ensure that the client has the right state..

We also discussed doing the xkb mapping on the server side.. and maybe per surface.. but thats would boil down to similar tasks.

Aaahnnd... we would have to find ways to tunnel that info through qt key events.. i believe..

Hmm why does this work at all right now?

Revision history for this message
Chris Halse Rogers (raof) wrote :

Hm. Couldn't you just keep the MirInputEventModifiers in the key_event() constructor and then not call mev::set_modifier(,seat->event_modifier()) on key events? That should then work just like it does today?

=============

+struct Seat

Class, surely? It has no public data members!

Otherwise looks good.

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

> Hm. Couldn't you just keep the MirInputEventModifiers in the key_event()
> constructor and then not call mev::set_modifier(,seat->event_modifier()) on
> key events? That should then work just like it does today?

Ah - so combine modifiers only for non key events, but keep per device modifers for key events..
So you cannot do for example ExternalKeyboard-Ctrl + BuiltinKeyboard-C to break stuff (which is what x11 currently does).

.... sounds good to me .. and simple to implement.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Woot! Exactly what I was after.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/client/mir/events/event_builders.h'
--- include/client/mir/events/event_builders.h 2015-10-02 04:27:33 +0000
+++ include/client/mir/events/event_builders.h 2015-10-26 14:13:05 +0000
@@ -58,6 +58,8 @@
58 uint64_t mac, MirKeyboardAction action, xkb_keysym_t key_code,58 uint64_t mac, MirKeyboardAction action, xkb_keysym_t key_code,
59 int scan_code, MirInputEventModifiers modifiers);59 int scan_code, MirInputEventModifiers modifiers);
6060
61void set_modifier(MirEvent& event, MirInputEventModifiers modifiers);
62
61// Deprecated version without mac63// Deprecated version without mac
62EventUPtr make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,64EventUPtr make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
63 MirKeyboardAction action, xkb_keysym_t key_code,65 MirKeyboardAction action, xkb_keysym_t key_code,
6466
=== modified file 'include/platform/mir/input/event_builder.h'
--- include/platform/mir/input/event_builder.h 2015-08-24 23:25:00 +0000
+++ include/platform/mir/input/event_builder.h 2015-10-26 14:13:05 +0000
@@ -38,18 +38,16 @@
38 virtual ~EventBuilder() = default;38 virtual ~EventBuilder() = default;
39 using Timestamp = std::chrono::nanoseconds;39 using Timestamp = std::chrono::nanoseconds;
4040
41 virtual EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code,41 virtual EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code) = 0;
42 MirInputEventModifiers modifiers) = 0;
4342
44 virtual EventUPtr touch_event(Timestamp timestamp, MirInputEventModifiers modifiers) = 0;43 virtual EventUPtr touch_event(Timestamp timestamp) = 0;
45 virtual void add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action, MirTouchTooltype tooltype,44 virtual void add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action, MirTouchTooltype tooltype,
46 float x_axis_value, float y_axis_value, float pressure_value, float touch_major_value,45 float x_axis_value, float y_axis_value, float pressure_value, float touch_major_value,
47 float touch_minor_value, float size_value) = 0;46 float touch_minor_value, float size_value) = 0;
4847
49 virtual EventUPtr pointer_event(Timestamp timestamp, MirInputEventModifiers modifiers, MirPointerAction action,48 virtual EventUPtr pointer_event(Timestamp timestamp, MirPointerAction action, MirPointerButtons buttons_pressed,
50 MirPointerButtons buttons_pressed, float x_axis_value, float y_axis_value,49 float x_axis_value, float y_axis_value, float hscroll_value, float vscroll_value,
51 float hscroll_value, float vscroll_value, float relative_x_value,50 float relative_x_value, float relative_y_value) = 0;
52 float relative_y_value) = 0;
5351
54 virtual EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) = 0;52 virtual EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) = 0;
5553
5654
=== modified file 'include/test/mir/test/event_matchers.h'
--- include/test/mir/test/event_matchers.h 2015-10-13 16:25:36 +0000
+++ include/test/mir/test/event_matchers.h 2015-10-26 14:13:05 +0000
@@ -353,6 +353,14 @@
353 return true;353 return true;
354}354}
355355
356MATCHER_P(PointerEventWithModifiers, modifiers, "")
357{
358 auto pev = maybe_pointer_event(to_address(arg));
359 if (pev && mir_pointer_event_modifiers(pev) == modifiers)
360 return true;
361 return false;
362}
363
356MATCHER_P2(PointerEventWithDiff, dx, dy, "")364MATCHER_P2(PointerEventWithDiff, dx, dy, "")
357{365{
358 auto pev = maybe_pointer_event(to_address(arg));366 auto pev = maybe_pointer_event(to_address(arg));
359367
=== modified file 'src/client/events/event_builders.cpp'
--- src/client/events/event_builders.cpp 2015-10-07 12:07:00 +0000
+++ src/client/events/event_builders.cpp 2015-10-26 14:13:05 +0000
@@ -165,6 +165,28 @@
165 return make_event_uptr(e);165 return make_event_uptr(e);
166}166}
167167
168
169void mev::set_modifier(MirEvent& event, MirInputEventModifiers modifiers)
170{
171 switch(event.type)
172 {
173 case mir_event_type_key:
174 {
175 auto& kev = event.key;
176 kev.modifiers = modifiers;
177 break;
178 }
179 case mir_event_type_motion:
180 {
181 auto& mev = event.motion;
182 mev.modifiers = modifiers;
183 break;
184 }
185 default:
186 BOOST_THROW_EXCEPTION(std::invalid_argument("Input event modifiers are only valid for pointer, key and touch events."));
187 }
188}
189
168// Deprecated version without mac190// Deprecated version without mac
169mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,191mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
170 MirKeyboardAction action, xkb_keysym_t key_code,192 MirKeyboardAction action, xkb_keysym_t key_code,
171193
=== modified file 'src/client/symbols.map'
--- src/client/symbols.map 2015-10-08 21:11:44 +0000
+++ src/client/symbols.map 2015-10-26 14:13:05 +0000
@@ -243,3 +243,11 @@
243 mir::operator???std::ostream???Mir*243 mir::operator???std::ostream???Mir*
244 }; 244 };
245};245};
246
247MIR_CLIENT_DETAIL_unreleased {
248 global:
249 extern "C++" {
250 mir::events::set_modifier*;
251 };
252} MIR_CLIENT_DETAIL_9;
253
246254
=== modified file 'src/platforms/evdev/CMakeLists.txt'
--- src/platforms/evdev/CMakeLists.txt 2015-10-05 20:17:26 +0000
+++ src/platforms/evdev/CMakeLists.txt 2015-10-26 14:13:05 +0000
@@ -8,7 +8,7 @@
88
9add_library(mirevdevutilsobjects OBJECT9add_library(mirevdevutilsobjects OBJECT
10 evdev_device_detection.cpp10 evdev_device_detection.cpp
11 input_modifier_utils.cpp11 button_utils.cpp
12 )12 )
1313
14add_library(mirplatforminputevdevobjects OBJECT14add_library(mirplatforminputevdevobjects OBJECT
@@ -34,8 +34,7 @@
34)34)
3535
36target_link_libraries(mirplatforminputevdev36target_link_libraries(mirplatforminputevdev
37 mirplatform37 mirplatform # udev wrapper
38 mirclient
39 ${Boost_PROGRAM_OPTIONS_LIBRARY}38 ${Boost_PROGRAM_OPTIONS_LIBRARY}
40 ${LIBINPUT_LDFLAGS} ${LIBINPUT_LIBRARIES}39 ${LIBINPUT_LDFLAGS} ${LIBINPUT_LIBRARIES}
41)40)
4241
=== added file 'src/platforms/evdev/button_utils.cpp'
--- src/platforms/evdev/button_utils.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/evdev/button_utils.cpp 2015-10-26 14:13:05 +0000
@@ -0,0 +1,44 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#include "button_utils.h"
20#include "boost/throw_exception.hpp"
21
22#include "linux/input.h"
23
24#include <stdexcept>
25
26namespace mie = mir::input::evdev;
27
28MirPointerButton mie::to_pointer_button(int button, MirPointerHandedness handedness)
29{
30 switch(button)
31 {
32 case BTN_LEFT: return (handedness == mir_pointer_handedness_right)
33 ? mir_pointer_button_primary
34 : mir_pointer_button_secondary;
35 case BTN_RIGHT: return (handedness == mir_pointer_handedness_right)
36 ? mir_pointer_button_secondary
37 : mir_pointer_button_primary;
38 case BTN_MIDDLE: return mir_pointer_button_tertiary;
39 case BTN_BACK: return mir_pointer_button_back;
40 case BTN_FORWARD: return mir_pointer_button_forward;
41 }
42 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid mouse button"));
43}
44
045
=== added file 'src/platforms/evdev/button_utils.h'
--- src/platforms/evdev/button_utils.h 1970-01-01 00:00:00 +0000
+++ src/platforms/evdev/button_utils.h 2015-10-26 14:13:05 +0000
@@ -0,0 +1,36 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_INPUT_EVDEV_BUTTON_UTILS_H_
20#define MIR_INPUT_EVDEV_BUTTON_UTILS_H_
21
22#include "mir_toolkit/event.h"
23#include "mir_toolkit/mir_input_device.h"
24
25namespace mir
26{
27namespace input
28{
29namespace evdev
30{
31MirPointerButton to_pointer_button(int button, MirPointerHandedness handedness);
32}
33}
34}
35
36#endif
037
=== modified file 'src/platforms/evdev/libinput_device.cpp'
--- src/platforms/evdev/libinput_device.cpp 2015-10-23 16:32:32 +0000
+++ src/platforms/evdev/libinput_device.cpp 2015-10-26 14:13:05 +0000
@@ -19,8 +19,8 @@
19#include "libinput_device.h"19#include "libinput_device.h"
20#include "libinput_ptr.h"20#include "libinput_ptr.h"
21#include "libinput_device_ptr.h"21#include "libinput_device_ptr.h"
22#include "input_modifier_utils.h"
23#include "evdev_device_detection.h"22#include "evdev_device_detection.h"
23#include "button_utils.h"
2424
25#include "mir/input/input_sink.h"25#include "mir/input/input_sink.h"
26#include "mir/input/input_report.h"26#include "mir/input/input_report.h"
@@ -55,8 +55,7 @@
5555
56mie::LibInputDevice::LibInputDevice(std::shared_ptr<mi::InputReport> const& report, char const* path,56mie::LibInputDevice::LibInputDevice(std::shared_ptr<mi::InputReport> const& report, char const* path,
57 LibInputDevicePtr dev)57 LibInputDevicePtr dev)
58 : report{report}, accumulated_touch_event{nullptr, null_deleter}, pointer_pos{0, 0}, modifier_state{0},58 : report{report}, accumulated_touch_event{nullptr, null_deleter}, pointer_pos{0, 0}, button_state{0}
59 button_state{0}
60{59{
61 add_device_of_group(path, std::move(dev));60 add_device_of_group(path, std::move(dev));
62}61}
@@ -140,18 +139,7 @@
140 auto const code = libinput_event_keyboard_get_key(keyboard);139 auto const code = libinput_event_keyboard_get_key(keyboard);
141 report->received_event_from_kernel(time.count(), EV_KEY, code, action);140 report->received_event_from_kernel(time.count(), EV_KEY, code, action);
142141
143 auto event = builder->key_event(time,142 return builder->key_event(time, action, xkb_keysym_t{0}, code);
144 action,
145 xkb_keysym_t{0},
146 code,
147 mie::expand_modifiers(modifier_state));
148
149 if (action == mir_keyboard_action_down)
150 modifier_state |= mie::to_modifiers(code);
151 else
152 modifier_state &= ~mie::to_modifiers(code);
153
154 return event;
155}143}
156144
157mir::EventUPtr mie::LibInputDevice::convert_button_event(libinput_event_pointer* pointer)145mir::EventUPtr mie::LibInputDevice::convert_button_event(libinput_event_pointer* pointer)
@@ -175,11 +163,8 @@
175 else163 else
176 button_state = MirPointerButton(button_state & ~uint32_t(pointer_button));164 button_state = MirPointerButton(button_state & ~uint32_t(pointer_button));
177165
178 auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,166 return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
179 pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,167 hscroll_value, vscroll_value, relative_x_value, relative_y_value);
180 vscroll_value, relative_x_value, relative_y_value);
181
182 return event;
183}168}
184169
185mir::EventUPtr mie::LibInputDevice::convert_motion_event(libinput_event_pointer* pointer)170mir::EventUPtr mie::LibInputDevice::convert_motion_event(libinput_event_pointer* pointer)
@@ -198,11 +183,8 @@
198183
199 sink->confine_pointer(pointer_pos);184 sink->confine_pointer(pointer_pos);
200185
201 auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,186 return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
202 pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,187 hscroll_value, vscroll_value, movement.dx.as_float(), movement.dy.as_float());
203 vscroll_value, movement.dx.as_float(), movement.dy.as_float());
204
205 return event;
206}188}
207189
208mir::EventUPtr mie::LibInputDevice::convert_absolute_motion_event(libinput_event_pointer* pointer)190mir::EventUPtr mie::LibInputDevice::convert_absolute_motion_event(libinput_event_pointer* pointer)
@@ -222,10 +204,8 @@
222204
223 sink->confine_pointer(pointer_pos);205 sink->confine_pointer(pointer_pos);
224206
225 auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,207 return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
226 pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,208 hscroll_value, vscroll_value, movement.dx.as_float(), movement.dy.as_float());
227 vscroll_value, movement.dx.as_float(), movement.dy.as_float());
228 return event;
229}209}
230210
231mir::EventUPtr mie::LibInputDevice::convert_axis_event(libinput_event_pointer* pointer)211mir::EventUPtr mie::LibInputDevice::convert_axis_event(libinput_event_pointer* pointer)
@@ -244,10 +224,8 @@
244 : 0.0f;224 : 0.0f;
245225
246 report->received_event_from_kernel(time.count(), EV_REL, 0, 0);226 report->received_event_from_kernel(time.count(), EV_REL, 0, 0);
247 auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,227 return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
248 pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,228 hscroll_value, vscroll_value, relative_x_value, relative_y_value);
249 vscroll_value, relative_x_value, relative_y_value);
250 return event;
251}229}
252230
253MirEvent& mie::LibInputDevice::get_accumulated_touch_event(std::chrono::nanoseconds timestamp)231MirEvent& mie::LibInputDevice::get_accumulated_touch_event(std::chrono::nanoseconds timestamp)
@@ -255,7 +233,7 @@
255 if (!accumulated_touch_event)233 if (!accumulated_touch_event)
256 {234 {
257 report->received_event_from_kernel(timestamp.count(), EV_SYN, 0, 0);235 report->received_event_from_kernel(timestamp.count(), EV_SYN, 0, 0);
258 accumulated_touch_event = builder->touch_event(timestamp, mie::expand_modifiers(modifier_state));236 accumulated_touch_event = builder->touch_event(timestamp);
259 }237 }
260238
261 return *accumulated_touch_event;239 return *accumulated_touch_event;
262240
=== modified file 'src/platforms/evdev/libinput_device.h'
--- src/platforms/evdev/libinput_device.h 2015-10-23 16:32:32 +0000
+++ src/platforms/evdev/libinput_device.h 2015-10-26 14:13:05 +0000
@@ -88,7 +88,6 @@
8888
89 InputDeviceInfo info;89 InputDeviceInfo info;
90 mir::geometry::Point pointer_pos;90 mir::geometry::Point pointer_pos;
91 MirInputEventModifiers modifier_state;
92 MirPointerButtons button_state;91 MirPointerButtons button_state;
93 double vertical_scroll_scale{1.0};92 double vertical_scroll_scale{1.0};
94 double horizontal_scroll_scale{1.0};93 double horizontal_scroll_scale{1.0};
9594
=== modified file 'src/platforms/mesa/server/x11/input/input_platform.cpp'
--- src/platforms/mesa/server/x11/input/input_platform.cpp 2015-10-15 16:56:07 +0000
+++ src/platforms/mesa/server/x11/input/input_platform.cpp 2015-10-26 14:13:05 +0000
@@ -127,16 +127,6 @@
127#endif127#endif
128 XLookupString(&xkev, str, STRMAX, &keysym, NULL);128 XLookupString(&xkev, str, STRMAX, &keysym, NULL);
129129
130 MirInputEventModifiers modifiers = mir_input_event_modifier_none;
131 if (xkev.state & ShiftMask)
132 modifiers |= mir_input_event_modifier_shift;
133 if (xkev.state & ControlMask)
134 modifiers |= mir_input_event_modifier_ctrl;
135 if (xkev.state & Mod1Mask)
136 modifiers |= mir_input_event_modifier_alt;
137 if (xkev.state & Mod4Mask)
138 modifiers |= mir_input_event_modifier_meta;
139
140 auto event_time =130 auto event_time =
141 std::chrono::duration_cast<std::chrono::nanoseconds>(131 std::chrono::duration_cast<std::chrono::nanoseconds>(
142 std::chrono::milliseconds{xkev.time});132 std::chrono::milliseconds{xkev.time});
@@ -155,8 +145,7 @@
155 mir_keyboard_action_down :145 mir_keyboard_action_down :
156 mir_keyboard_action_up,146 mir_keyboard_action_up,
157 keysym,147 keysym,
158 xkev.keycode-8,148 xkev.keycode-8
159 modifiers
160 )149 )
161 );150 );
162 break;151 break;
@@ -185,16 +174,6 @@
185#endif174#endif
186 break;175 break;
187 }176 }
188 MirInputEventModifiers modifiers = mir_input_event_modifier_none;
189 if (xbev.state & ShiftMask)
190 modifiers |= mir_input_event_modifier_shift;
191 if (xbev.state & ControlMask)
192 modifiers |= mir_input_event_modifier_ctrl;
193 if (xbev.state & Mod1Mask)
194 modifiers |= mir_input_event_modifier_alt;
195 if (xbev.state & Mod4Mask)
196 modifiers |= mir_input_event_modifier_meta;
197
198 auto event_time =177 auto event_time =
199 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds{xbev.time});178 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds{xbev.time});
200179
@@ -215,15 +194,15 @@
215194
216#ifdef MIR_ON_X11_INPUT_VERBOSE195#ifdef MIR_ON_X11_INPUT_VERBOSE
217 mir::log_info("Mir button event : x=%d, y=%d, "196 mir::log_info("Mir button event : x=%d, y=%d, "
218 "buttons_pressed=0x%0X, modifiers=0x%0X, event_time=%" PRId64,197 "buttons_pressed=0x%0X, event_time=%" PRId64,
219 xbev.x, xbev.y, buttons_pressed, modifiers, event_time);198 xbev.x, xbev.y, buttons_pressed, event_time);
220#endif199#endif
200
221 if ((xbev.button == Button4) || (xbev.button == Button5))201 if ((xbev.button == Button4) || (xbev.button == Button5))
222 { // scroll event202 { // scroll event
223 core_pointer->sink->handle_input(203 core_pointer->sink->handle_input(
224 *core_pointer->builder->pointer_event(204 *core_pointer->builder->pointer_event(
225 event_time,205 event_time,
226 modifiers,
227 mir_pointer_action_motion,206 mir_pointer_action_motion,
228 0,207 0,
229 xbev.x,208 xbev.x,
@@ -240,7 +219,6 @@
240 core_pointer->sink->handle_input(219 core_pointer->sink->handle_input(
241 *core_pointer->builder->pointer_event(220 *core_pointer->builder->pointer_event(
242 event_time,221 event_time,
243 modifiers,
244 xbev.type == ButtonPress ?222 xbev.type == ButtonPress ?
245 mir_pointer_action_button_down :223 mir_pointer_action_button_down :
246 mir_pointer_action_button_up,224 mir_pointer_action_button_up,
@@ -270,15 +248,6 @@
270 xmev.root, xmev.subwindow, xmev.time, xmev.x, xmev.y, xmev.x_root,248 xmev.root, xmev.subwindow, xmev.time, xmev.x, xmev.y, xmev.x_root,
271 xmev.y_root, xmev.state, xmev.is_hint == NotifyNormal ? "no" : "yes", xmev.same_screen);249 xmev.y_root, xmev.state, xmev.is_hint == NotifyNormal ? "no" : "yes", xmev.same_screen);
272#endif250#endif
273 MirInputEventModifiers modifiers = mir_input_event_modifier_none;
274 if (xmev.state & ShiftMask)
275 modifiers |= mir_input_event_modifier_shift;
276 if (xmev.state & ControlMask)
277 modifiers |= mir_input_event_modifier_ctrl;
278 if (xmev.state & Mod1Mask)
279 modifiers |= mir_input_event_modifier_alt;
280 if (xmev.state & Mod4Mask)
281 modifiers |= mir_input_event_modifier_meta;
282251
283 auto event_time =252 auto event_time =
284 std::chrono::duration_cast<std::chrono::nanoseconds>(253 std::chrono::duration_cast<std::chrono::nanoseconds>(
@@ -298,13 +267,12 @@
298267
299#ifdef MIR_ON_X11_INPUT_VERBOSE268#ifdef MIR_ON_X11_INPUT_VERBOSE
300 mir::log_info("Mir pointer event : "269 mir::log_info("Mir pointer event : "
301 "x=%d, y=%d, buttons_pressed=0x%0X, modifiers=0x%0X, event_time=%" PRId64,270 "x=%d, y=%d, buttons_pressed=0x%0X, event_time=%" PRId64,
302 xmev.x, xmev.y, buttons_pressed, modifiers, event_time);271 xmev.x, xmev.y, buttons_pressed, event_time);
303#endif272#endif
304 core_pointer->sink->handle_input(273 core_pointer->sink->handle_input(
305 *core_pointer->builder->pointer_event(274 *core_pointer->builder->pointer_event(
306 event_time,275 event_time,
307 modifiers,
308 mir_pointer_action_motion,276 mir_pointer_action_motion,
309 buttons_pressed,277 buttons_pressed,
310 xmev.x,278 xmev.x,
311279
=== modified file 'src/server/input/CMakeLists.txt'
--- src/server/input/CMakeLists.txt 2015-10-12 19:30:14 +0000
+++ src/server/input/CMakeLists.txt 2015-10-26 14:13:05 +0000
@@ -8,6 +8,8 @@
8 default_event_builder.cpp8 default_event_builder.cpp
9 default_input_manager.cpp9 default_input_manager.cpp
10 default_input_device_hub.cpp10 default_input_device_hub.cpp
11 input_modifier_utils.cpp
12 seat.cpp
1113
12 surface_input_dispatcher.cpp14 surface_input_dispatcher.cpp
13 event_filter_chain_dispatcher.cpp15 event_filter_chain_dispatcher.cpp
1416
=== modified file 'src/server/input/default_event_builder.cpp'
--- src/server/input/default_event_builder.cpp 2015-10-09 00:15:44 +0000
+++ src/server/input/default_event_builder.cpp 2015-10-26 14:13:05 +0000
@@ -33,21 +33,21 @@
33}33}
3434
35mir::EventUPtr mi::DefaultEventBuilder::key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code,35mir::EventUPtr mi::DefaultEventBuilder::key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code,
36 int scan_code, MirInputEventModifiers modifiers)36 int scan_code)
37{37{
38 uint64_t mac = cookie_factory->timestamp_to_cookie(timestamp.count()).mac;38 uint64_t mac = cookie_factory->timestamp_to_cookie(timestamp.count()).mac;
39 return me::make_event(device_id, timestamp, mac, action, key_code, scan_code, modifiers);39 return me::make_event(device_id, timestamp, mac, action, key_code, scan_code, mir_input_event_modifier_none);
40}40}
4141
42mir::EventUPtr mi::DefaultEventBuilder::touch_event(Timestamp timestamp, MirInputEventModifiers modifiers)42mir::EventUPtr mi::DefaultEventBuilder::touch_event(Timestamp timestamp)
43{43{
44 return me::make_event(device_id, timestamp, 0, modifiers);44 return me::make_event(device_id, timestamp, 0, mir_input_event_modifier_none);
45}45}
4646
47void mi::DefaultEventBuilder::add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action,47void mi::DefaultEventBuilder::add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action,
48 MirTouchTooltype tooltype, float x_axis_value, float y_axis_value,48 MirTouchTooltype tooltype, float x_axis_value, float y_axis_value,
49 float pressure_value, float touch_major_value,49 float pressure_value, float touch_major_value, float touch_minor_value,
50 float touch_minor_value, float size_value)50 float size_value)
51{51{
52 if (action == mir_touch_action_up || action == mir_touch_action_down)52 if (action == mir_touch_action_up || action == mir_touch_action_down)
53 {53 {
@@ -59,17 +59,15 @@
59 touch_minor_value, size_value);59 touch_minor_value, size_value);
60}60}
6161
62mir::EventUPtr mi::DefaultEventBuilder::pointer_event(Timestamp timestamp, MirInputEventModifiers modifiers,62mir::EventUPtr mi::DefaultEventBuilder::pointer_event(Timestamp timestamp, MirPointerAction action,
63 MirPointerAction action, MirPointerButtons buttons_pressed,63 MirPointerButtons buttons_pressed, float x_axis_value,
64 float x_axis_value, float y_axis_value, float hscroll_value,64 float y_axis_value, float hscroll_value, float vscroll_value,
65 float vscroll_value, float relative_x_value,65 float relative_x_value, float relative_y_value)
66 float relative_y_value)
67{66{
68 uint64_t mac = 0;67 uint64_t mac = 0;
69 if (action == mir_pointer_action_button_up || action == mir_pointer_action_button_down)68 if (action == mir_pointer_action_button_up || action == mir_pointer_action_button_down)
70 mac = cookie_factory->timestamp_to_cookie(timestamp.count()).mac;69 mac = cookie_factory->timestamp_to_cookie(timestamp.count()).mac;
7170 return me::make_event(device_id, timestamp, mac, mir_input_event_modifier_none, action, buttons_pressed, x_axis_value, y_axis_value,
72 return me::make_event(device_id, timestamp, mac, modifiers, action, buttons_pressed, x_axis_value, y_axis_value,
73 hscroll_value, vscroll_value, relative_x_value, relative_y_value);71 hscroll_value, vscroll_value, relative_x_value, relative_y_value);
74}72}
7573
7674
=== modified file 'src/server/input/default_event_builder.h'
--- src/server/input/default_event_builder.h 2015-10-08 00:23:43 +0000
+++ src/server/input/default_event_builder.h 2015-10-26 14:13:05 +0000
@@ -37,18 +37,16 @@
37 explicit DefaultEventBuilder(MirInputDeviceId device_id,37 explicit DefaultEventBuilder(MirInputDeviceId device_id,
38 std::shared_ptr<cookie::CookieFactory> const& cookie_factory);38 std::shared_ptr<cookie::CookieFactory> const& cookie_factory);
3939
40 EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code,40 EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code) override;
41 MirInputEventModifiers modifiers) override;
4241
43 EventUPtr touch_event(Timestamp timestamp, MirInputEventModifiers modifiers) override;42 EventUPtr touch_event(Timestamp timestamp) override;
44 void add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action, MirTouchTooltype tooltype,43 void add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action, MirTouchTooltype tooltype,
45 float x_axis_value, float y_axis_value, float pressure_value, float touch_major_value,44 float x_axis_value, float y_axis_value, float pressure_value, float touch_major_value,
46 float touch_minor_value, float size_value) override;45 float touch_minor_value, float size_value) override;
4746
48 EventUPtr pointer_event(Timestamp timestamp, MirInputEventModifiers modifiers, MirPointerAction action,47 EventUPtr pointer_event(Timestamp timestamp, MirPointerAction action, MirPointerButtons buttons_pressed,
49 MirPointerButtons buttons_pressed, float x_axis_value, float y_axis_value,48 float x_axis_value, float y_axis_value, float hscroll_value, float vscroll_value,
50 float hscroll_value, float vscroll_value, float relative_x_value,49 float relative_x_value, float relative_y_value) override;
51 float relative_y_value) override;
5250
53 EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) override;51 EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) override;
5452
5553
=== modified file 'src/server/input/default_input_device_hub.cpp'
--- src/server/input/default_input_device_hub.cpp 2015-10-08 00:23:43 +0000
+++ src/server/input/default_input_device_hub.cpp 2015-10-26 14:13:05 +0000
@@ -19,11 +19,13 @@
19#include "default_input_device_hub.h"19#include "default_input_device_hub.h"
20#include "device_handle.h"20#include "device_handle.h"
2121
22#include "seat.h"
22#include "mir/input/input_dispatcher.h"23#include "mir/input/input_dispatcher.h"
23#include "mir/input/input_device.h"24#include "mir/input/input_device.h"
24#include "mir/input/input_device_observer.h"25#include "mir/input/input_device_observer.h"
25#include "mir/input/cursor_listener.h"
26#include "mir/input/input_region.h"26#include "mir/input/input_region.h"
27#include "mir/geometry/point.h"
28#include "mir/events/event_builders.h"
27#include "mir/dispatch/multiplexing_dispatchable.h"29#include "mir/dispatch/multiplexing_dispatchable.h"
28#include "mir/server_action_queue.h"30#include "mir/server_action_queue.h"
29#include "mir/cookie_factory.h"31#include "mir/cookie_factory.h"
@@ -36,6 +38,8 @@
36#include <atomic>38#include <atomic>
3739
38namespace mi = mir::input;40namespace mi = mir::input;
41namespace geom = mir::geometry;
42namespace mev = mir::events;
3943
40mi::DefaultInputDeviceHub::DefaultInputDeviceHub(44mi::DefaultInputDeviceHub::DefaultInputDeviceHub(
41 std::shared_ptr<mi::InputDispatcher> const& input_dispatcher,45 std::shared_ptr<mi::InputDispatcher> const& input_dispatcher,
@@ -45,9 +49,13 @@
45 std::shared_ptr<CursorListener> const& cursor_listener,49 std::shared_ptr<CursorListener> const& cursor_listener,
46 std::shared_ptr<InputRegion> const& input_region,50 std::shared_ptr<InputRegion> const& input_region,
47 std::shared_ptr<mir::cookie::CookieFactory> const& cookie_factory)51 std::shared_ptr<mir::cookie::CookieFactory> const& cookie_factory)
48 : input_dispatcher(input_dispatcher), input_dispatchable{input_multiplexer}, observer_queue(observer_queue),52 : input_dispatcher(input_dispatcher),
49 touch_visualizer(touch_visualizer), cursor_listener(cursor_listener), input_region(input_region),53 input_dispatchable{input_multiplexer},
50 cookie_factory(cookie_factory), device_id_generator{0}54 observer_queue(observer_queue),
55 input_region(input_region),
56 cookie_factory(cookie_factory),
57 seat(touch_visualizer, cursor_listener),
58 device_id_generator{0}
51{59{
52}60}
5361
@@ -67,9 +75,10 @@
67 {75 {
68 // send input device info to observer loop..76 // send input device info to observer loop..
69 devices.push_back(std::make_unique<RegisteredDevice>(77 devices.push_back(std::make_unique<RegisteredDevice>(
70 device, create_new_device_id(), input_dispatcher, input_dispatchable, cookie_factory, this));78 device, create_new_device_id(), input_dispatcher, input_dispatchable, cookie_factory, this, &seat));
7179
72 auto const& dev = devices.back();80 auto const& dev = devices.back();
81 seat.add_device(dev->id());
7382
74 auto handle = std::make_shared<DefaultDevice>(83 auto handle = std::make_shared<DefaultDevice>(
75 dev->id(), device->get_device_info());84 dev->id(), device->get_device_info());
@@ -104,6 +113,7 @@
104 if (item->device_matches(device))113 if (item->device_matches(device))
105 {114 {
106 item->stop();115 item->stop();
116 seat.remove_device(item->id());
107117
108 // send input device info to observer queue..118 // send input device info to observer queue..
109 observer_queue->enqueue(119 observer_queue->enqueue(
@@ -131,9 +141,10 @@
131 std::shared_ptr<InputDispatcher> const& dispatcher,141 std::shared_ptr<InputDispatcher> const& dispatcher,
132 std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,142 std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,
133 std::shared_ptr<mir::cookie::CookieFactory> const& cookie_factory,143 std::shared_ptr<mir::cookie::CookieFactory> const& cookie_factory,
134 DefaultInputDeviceHub* hub)144 DefaultInputDeviceHub* hub,
145 Seat* seat)
135 : device_id(device_id), builder(device_id, cookie_factory), device(dev), dispatcher(dispatcher),146 : device_id(device_id), builder(device_id, cookie_factory), device(dev), dispatcher(dispatcher),
136 multiplexer(multiplexer), hub(hub)147 multiplexer(multiplexer), hub(hub), seat(seat)
137{148{
138}149}
139150
@@ -154,50 +165,17 @@
154 if (type != mir_event_type_input)165 if (type != mir_event_type_input)
155 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid input event receivd from device"));166 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid input event receivd from device"));
156167
157 update_spots(mir_event_get_input_event(&event));168 auto input_event = mir_event_get_input_event(&event);
158 notify_cursor_listener(mir_event_get_input_event(&event));169 seat->update_seat_properties(input_event);
170
171 if (mir_input_event_type_key == mir_input_event_get_type(input_event))
172 mev::set_modifier(event, seat->event_modifier(mir_input_event_get_device_id(input_event)));
173 else
174 mev::set_modifier(event, seat->event_modifier());
175
159 dispatcher->dispatch(event);176 dispatcher->dispatch(event);
160}177}
161178
162void mi::DefaultInputDeviceHub::RegisteredDevice::notify_cursor_listener(MirInputEvent const* event)
163{
164 if (mir_input_event_get_type(event) != mir_input_event_type_pointer)
165 return;
166
167 auto pointer_ev = mir_input_event_get_pointer_event(event);
168 hub->cursor_listener->cursor_moved_to(
169 mir_pointer_event_axis_value(pointer_ev, mir_pointer_axis_x),
170 mir_pointer_event_axis_value(pointer_ev, mir_pointer_axis_y)
171 );
172}
173
174void mi::DefaultInputDeviceHub::RegisteredDevice::update_spots(MirInputEvent const* event)
175{
176 if (mir_input_event_get_type(event) != mir_input_event_type_touch)
177 return;
178
179 auto const* touch_event = mir_input_event_get_touch_event(event);
180 auto count = mir_touch_event_point_count(touch_event);
181 touch_spots.reserve(count);
182 touch_spots.clear();
183 for (decltype(count) i = 0; i != count; ++i)
184 {
185 if (mir_touch_event_action(touch_event, i) == mir_touch_action_up)
186 continue;
187 touch_spots.push_back(mi::TouchVisualizer::Spot{
188 {mir_touch_event_axis_value(touch_event, i, mir_touch_axis_x),
189 mir_touch_event_axis_value(touch_event, i, mir_touch_axis_y)},
190 mir_touch_event_axis_value(touch_event, i, mir_touch_axis_pressure)});
191 }
192
193 hub->update_spots();
194}
195
196std::vector<mir::input::TouchVisualizer::Spot> const& mi::DefaultInputDeviceHub::RegisteredDevice::spots() const
197{
198 return touch_spots;
199}
200
201bool mi::DefaultInputDeviceHub::RegisteredDevice::device_matches(std::shared_ptr<InputDevice> const& dev) const179bool mi::DefaultInputDeviceHub::RegisteredDevice::device_matches(std::shared_ptr<InputDevice> const& dev) const
202{180{
203 return dev == device;181 return dev == device;
@@ -278,13 +256,3 @@
278256
279 handles.erase(handle_it, end(handles));257 handles.erase(handle_it, end(handles));
280}258}
281
282void mi::DefaultInputDeviceHub::update_spots()
283{
284 std::vector<TouchVisualizer::Spot> spots;
285
286 for (auto const& dev : devices)
287 spots.insert(end(spots), begin(dev->spots()), end(dev->spots()));
288
289 touch_visualizer->visualize_touches(spots);
290}
291259
=== modified file 'src/server/input/default_input_device_hub.h'
--- src/server/input/default_input_device_hub.h 2015-10-08 00:23:43 +0000
+++ src/server/input/default_input_device_hub.h 2015-10-26 14:13:05 +0000
@@ -20,12 +20,12 @@
20#define MIR_INPUT_DEFAULT_INPUT_DEVICE_HUB_H_20#define MIR_INPUT_DEFAULT_INPUT_DEVICE_HUB_H_
2121
22#include "default_event_builder.h"22#include "default_event_builder.h"
23#include "seat.h"
2324
24#include "mir/input/input_device_registry.h"25#include "mir/input/input_device_registry.h"
25#include "mir/input/input_sink.h"26#include "mir/input/input_sink.h"
26#include "mir/input/input_device_hub.h"27#include "mir/input/input_device_hub.h"
27#include "mir/input/input_device_info.h"28#include "mir/input/input_device_info.h"
28#include "mir/input/touch_visualizer.h"
2929
30#include "mir_toolkit/event.h"30#include "mir_toolkit/event.h"
3131
@@ -82,10 +82,9 @@
82 std::shared_ptr<InputDispatcher> const input_dispatcher;82 std::shared_ptr<InputDispatcher> const input_dispatcher;
83 std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable;83 std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable;
84 std::shared_ptr<ServerActionQueue> const observer_queue;84 std::shared_ptr<ServerActionQueue> const observer_queue;
85 std::shared_ptr<TouchVisualizer> const touch_visualizer;
86 std::shared_ptr<CursorListener> const cursor_listener;
87 std::shared_ptr<InputRegion> const input_region;85 std::shared_ptr<InputRegion> const input_region;
88 std::shared_ptr<cookie::CookieFactory> const cookie_factory;86 std::shared_ptr<cookie::CookieFactory> const cookie_factory;
87 Seat seat;
8988
90 struct RegisteredDevice : public InputSink89 struct RegisteredDevice : public InputSink
91 {90 {
@@ -95,8 +94,8 @@
95 std::shared_ptr<InputDispatcher> const& dispatcher,94 std::shared_ptr<InputDispatcher> const& dispatcher,
96 std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,95 std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,
97 std::shared_ptr<cookie::CookieFactory> const& cookie_factory,96 std::shared_ptr<cookie::CookieFactory> const& cookie_factory,
98 DefaultInputDeviceHub* hub);97 DefaultInputDeviceHub* hub,
9998 Seat* seat);
100 void handle_input(MirEvent& event) override;99 void handle_input(MirEvent& event) override;
101 void confine_pointer(mir::geometry::Point& position) override;100 void confine_pointer(mir::geometry::Point& position) override;
102 mir::geometry::Rectangle bounding_rectangle() const override;101 mir::geometry::Rectangle bounding_rectangle() const override;
@@ -104,24 +103,21 @@
104 void start();103 void start();
105 void stop();104 void stop();
106 MirInputDeviceId id();105 MirInputDeviceId id();
107 std::vector<TouchVisualizer::Spot> const& spots() const;
108 private:106 private:
109 void update_spots(MirInputEvent const* event);
110 void notify_cursor_listener(MirInputEvent const* event);
111 MirInputDeviceId device_id;107 MirInputDeviceId device_id;
112 DefaultEventBuilder builder;108 DefaultEventBuilder builder;
113 std::shared_ptr<InputDevice> const device;109 std::shared_ptr<InputDevice> const device;
114 std::shared_ptr<InputDispatcher> const dispatcher;110 std::shared_ptr<InputDispatcher> const dispatcher;
115 std::shared_ptr<dispatch::MultiplexingDispatchable> const multiplexer;111 std::shared_ptr<dispatch::MultiplexingDispatchable> const multiplexer;
116 DefaultInputDeviceHub* hub;112 DefaultInputDeviceHub* hub;
117 std::vector<TouchVisualizer::Spot> touch_spots;113 Seat* seat;
118 friend class DefaultInputDeviceHub;114 friend class DefaultInputDeviceHub;
119 };115 };
120116
121 std::vector<std::shared_ptr<DefaultDevice>> handles;117 std::vector<std::shared_ptr<DefaultDevice>> handles;
122 std::vector<std::unique_ptr<RegisteredDevice>> devices;118 std::vector<std::unique_ptr<RegisteredDevice>> devices;
123 std::vector<std::shared_ptr<InputDeviceObserver>> observers;119 std::vector<std::shared_ptr<InputDeviceObserver>> observers;
124 120
125 MirInputDeviceId device_id_generator;121 MirInputDeviceId device_id_generator;
126};122};
127123
128124
=== renamed file 'src/platforms/evdev/input_modifier_utils.cpp' => 'src/server/input/input_modifier_utils.cpp'
--- src/platforms/evdev/input_modifier_utils.cpp 2015-10-20 03:30:00 +0000
+++ src/server/input/input_modifier_utils.cpp 2015-10-26 14:13:05 +0000
@@ -25,26 +25,9 @@
2525
26#include <stdexcept>26#include <stdexcept>
2727
28namespace mie = mir::input::evdev;28namespace mi = mir::input;
2929
30MirPointerButton mie::to_pointer_button(int button, MirPointerHandedness handedness)30MirInputEventModifiers mi::to_modifiers(int32_t scan_code)
31{
32 switch(button)
33 {
34 case BTN_LEFT: return (handedness == mir_pointer_handedness_right)
35 ? mir_pointer_button_primary
36 : mir_pointer_button_secondary;
37 case BTN_RIGHT: return (handedness == mir_pointer_handedness_right)
38 ? mir_pointer_button_secondary
39 : mir_pointer_button_primary;
40 case BTN_MIDDLE: return mir_pointer_button_tertiary;
41 case BTN_BACK: return mir_pointer_button_back;
42 case BTN_FORWARD: return mir_pointer_button_forward;
43 }
44 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid mouse button"));
45}
46
47MirInputEventModifiers mie::to_modifiers(int32_t scan_code)
48{31{
49 switch(scan_code)32 switch(scan_code)
50 {33 {
@@ -75,7 +58,7 @@
75 }58 }
76}59}
7760
78MirInputEventModifiers mie::expand_modifiers(MirInputEventModifiers modifiers)61MirInputEventModifiers mi::expand_modifiers(MirInputEventModifiers modifiers)
79{62{
80 if (modifiers == 0)63 if (modifiers == 0)
81 return mir_input_event_modifier_none;64 return mir_input_event_modifier_none;
@@ -95,4 +78,3 @@
95 return modifiers;78 return modifiers;
96}79}
9780
98
9981
=== renamed file 'src/platforms/evdev/input_modifier_utils.h' => 'src/server/input/input_modifier_utils.h'
--- src/platforms/evdev/input_modifier_utils.h 2015-10-20 03:30:00 +0000
+++ src/server/input/input_modifier_utils.h 2015-10-26 14:13:05 +0000
@@ -16,23 +16,18 @@
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */17 */
1818
19#ifndef MIR_INPUT_EVDEV_INPUT_MODIFIER_UTILS_H_19#ifndef MIR_INPUT_INPUT_MODIFIER_UTILS_H_
20#define MIR_INPUT_EVDEV_INPUT_MODIFIER_UTILS_H_20#define MIR_INPUT_INPUT_MODIFIER_UTILS_H_
2121
22#include "mir_toolkit/event.h"22#include "mir_toolkit/event.h"
23#include "mir_toolkit/mir_input_device.h"
2423
25namespace mir24namespace mir
26{25{
27namespace input26namespace input
28{27{
29namespace evdev
30{
31MirPointerButton to_pointer_button(int button, MirPointerHandedness handedness);
32MirInputEventModifiers to_modifiers(int32_t scan_code);28MirInputEventModifiers to_modifiers(int32_t scan_code);
33MirInputEventModifiers expand_modifiers(MirInputEventModifiers modifiers);29MirInputEventModifiers expand_modifiers(MirInputEventModifiers modifiers);
34}30}
35}31}
36}
3732
38#endif33#endif
3934
=== added file 'src/server/input/seat.cpp'
--- src/server/input/seat.cpp 1970-01-01 00:00:00 +0000
+++ src/server/input/seat.cpp 2015-10-26 14:13:05 +0000
@@ -0,0 +1,161 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by:
17 * Andreas Pokorny <andreas.pokorny@canonical.com>
18 */
19
20#include "seat.h"
21#include "mir/input/device.h"
22#include "mir/input/cursor_listener.h"
23
24#include "input_modifier_utils.h"
25
26#include <boost/throw_exception.hpp>
27
28#include <stdexcept>
29#include <algorithm>
30
31namespace mi = mir::input;
32
33mi::Seat::Seat(std::shared_ptr<TouchVisualizer> const& touch_visualizer,
34 std::shared_ptr<CursorListener> const& cursor_listener)
35 : touch_visualizer{touch_visualizer}, cursor_listener{cursor_listener}, modifier{0}
36{
37}
38
39void mi::Seat::add_device(MirInputDeviceId id)
40{
41 device_data[id];
42}
43
44void mi::Seat::remove_device(MirInputDeviceId id)
45{
46 auto stored_data = device_data.find(id);
47
48 if (stored_data == end(device_data))
49 BOOST_THROW_EXCEPTION(std::logic_error("Modifier for unknown device changed"));
50
51 bool mod_update_needed = stored_data->second.mod != mir_input_event_modifier_none;
52 bool spot_update_needed = !stored_data->second.spots.empty();
53
54 device_data.erase(stored_data);
55
56 if (mod_update_needed)
57 update_modifier();
58 if (spot_update_needed)
59 update_spots();
60}
61
62MirInputEventModifiers mi::Seat::event_modifier() const
63{
64 return expand_modifiers(modifier);
65}
66
67MirInputEventModifiers mi::Seat::event_modifier(MirInputDeviceId id) const
68{
69 auto stored_data = device_data.find(id);
70 if (stored_data == end(device_data))
71 BOOST_THROW_EXCEPTION(std::logic_error("Modifier for unknown device requested"));
72 return expand_modifiers(stored_data->second.mod);
73}
74
75void mi::Seat::update_seat_properties(MirInputEvent const* event)
76{
77 auto id = mir_input_event_get_device_id(event);
78
79 auto stored_data = device_data.find(id);
80
81 if (stored_data == end(device_data))
82 BOOST_THROW_EXCEPTION(std::logic_error("Modifier for unknown device changed"));
83
84 switch(mir_input_event_get_type(event))
85 {
86 case mir_input_event_type_key:
87 {
88 auto const* key = mir_input_event_get_keyboard_event(event);
89 if (stored_data->second.update_modifier(mir_keyboard_event_action(key),
90 mir_keyboard_event_scan_code(key)))
91 update_modifier();
92 break;
93 }
94 case mir_input_event_type_touch:
95 if (stored_data->second.update_spots(mir_input_event_get_touch_event(event)))
96 update_spots();
97 break;
98 case mir_input_event_type_pointer:
99 update_cursor(mir_input_event_get_pointer_event(event));
100 break;
101 default:
102 break;
103 }
104}
105
106bool mi::Seat::DeviceData::update_modifier(MirKeyboardAction key_action, int scan_code)
107{
108 auto mod_change = to_modifiers(scan_code);
109
110 if (mod_change == 0 || key_action == mir_keyboard_action_repeat)
111 return false;
112
113 if (key_action == mir_keyboard_action_down)
114 mod |= mod_change;
115 else if (key_action == mir_keyboard_action_up)
116 mod &= ~mod_change;
117
118 return true;
119}
120
121bool mi::Seat::DeviceData::update_spots(MirTouchEvent const* event)
122{
123 auto count = mir_touch_event_point_count(event);
124 spots.clear();
125 for (decltype(count) i = 0; i != count; ++i)
126 {
127 if (mir_touch_event_action(event, i) == mir_touch_action_up)
128 continue;
129 spots.push_back({{mir_touch_event_axis_value(event, i, mir_touch_axis_x),
130 mir_touch_event_axis_value(event, i, mir_touch_axis_y)},
131 mir_touch_event_axis_value(event, i, mir_touch_axis_pressure)});
132 }
133 return true;
134}
135
136void mi::Seat::update_spots()
137{
138 spots.clear();
139 for (auto const& dev : device_data)
140 spots.insert(end(spots), begin(dev.second.spots), end(dev.second.spots));
141
142 touch_visualizer->visualize_touches(spots);
143}
144
145void mi::Seat::update_modifier()
146{
147 modifier = std::accumulate(begin(device_data),
148 end(device_data),
149 MirInputEventModifiers{0},
150 [](auto const& acc, auto const& item)
151 {
152 return acc | item.second.mod;
153 });
154}
155
156void mi::Seat::update_cursor(MirPointerEvent const* event)
157{
158 cursor_listener->cursor_moved_to(mir_pointer_event_axis_value(event, mir_pointer_axis_x),
159 mir_pointer_event_axis_value(event, mir_pointer_axis_y));
160}
161
0162
=== added file 'src/server/input/seat.h'
--- src/server/input/seat.h 1970-01-01 00:00:00 +0000
+++ src/server/input/seat.h 2015-10-26 14:13:05 +0000
@@ -0,0 +1,74 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by:
17 * Andreas Pokorny <andreas.pokorny@canonical.com>
18 */
19
20#ifndef MIR_INPUT_DEFAULT_SEAT_H_
21#define MIR_INPUT_DEFAULT_SEAT_H_
22
23#include "mir/input/touch_visualizer.h"
24#include "mir_toolkit/event.h"
25#include <unordered_map>
26#include <memory>
27
28namespace mir
29{
30namespace input
31{
32class CursorListener;
33
34/*
35 * The seat bundles a group of devices. A cursor position, input event modifiers and the visible touch spots are properties
36 * controlled by this grouping of input devices.
37 */
38class Seat
39{
40public:
41 Seat(std::shared_ptr<TouchVisualizer> const& touch_visualizer, std::shared_ptr<CursorListener> const& cursor_listener);
42 void add_device(MirInputDeviceId);
43 void remove_device(MirInputDeviceId);
44
45 MirInputEventModifiers event_modifier() const;
46 MirInputEventModifiers event_modifier(MirInputDeviceId) const;
47 void update_seat_properties(MirInputEvent const* event);
48private:
49 void update_cursor(MirPointerEvent const* event);
50 void update_spots();
51 void update_modifier();
52
53 std::shared_ptr<TouchVisualizer> const touch_visualizer;
54 std::shared_ptr<CursorListener> const cursor_listener;
55
56 struct DeviceData
57 {
58 DeviceData() {}
59 bool update_modifier(MirKeyboardAction action, int scan_code);
60 bool update_spots(MirTouchEvent const* event);
61
62 MirInputEventModifiers mod{0};
63 std::vector<TouchVisualizer::Spot> spots;
64 };
65
66 MirInputEventModifiers modifier;
67 std::unordered_map<MirInputDeviceId, DeviceData> device_data;
68 std::vector<TouchVisualizer::Spot> spots;
69};
70
71}
72}
73
74#endif
075
=== modified file 'tests/mir_test_framework/fake_input_device_impl.cpp'
--- tests/mir_test_framework/fake_input_device_impl.cpp 2015-10-23 16:32:32 +0000
+++ tests/mir_test_framework/fake_input_device_impl.cpp 2015-10-26 14:13:05 +0000
@@ -27,8 +27,7 @@
27#include "mir/input/event_builder.h"27#include "mir/input/event_builder.h"
28#include "mir/dispatch/action_queue.h"28#include "mir/dispatch/action_queue.h"
29#include "mir/geometry/displacement.h"29#include "mir/geometry/displacement.h"
30#include "mir/module_deleter.h"30#include "src/platforms/evdev/button_utils.h"
31#include "src/platforms/evdev/input_modifier_utils.h"
3231
33#include "boost/throw_exception.hpp"32#include "boost/throw_exception.hpp"
3433
@@ -103,13 +102,7 @@
103 auto input_action =102 auto input_action =
104 (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down : mir_keyboard_action_up;103 (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down : mir_keyboard_action_up;
105104
106 auto event_modifiers = mie::expand_modifiers(modifiers);105 auto key_event = builder->key_event(event_time, input_action, key_code, key_params.scancode);
107 auto key_event = builder->key_event(event_time, input_action, key_code, key_params.scancode, event_modifiers);
108
109 if (key_params.action == synthesis::EventAction::Down)
110 modifiers |= mie::to_modifiers(key_params.scancode);
111 else
112 modifiers &= ~mie::to_modifiers(key_params.scancode);
113106
114 if (!sink)107 if (!sink)
115 BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));108 BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));
@@ -121,9 +114,7 @@
121 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(114 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
122 std::chrono::system_clock::now().time_since_epoch());115 std::chrono::system_clock::now().time_since_epoch());
123 auto action = update_buttons(button.action, mie::to_pointer_button(button.button, settings.handedness));116 auto action = update_buttons(button.action, mie::to_pointer_button(button.button, settings.handedness));
124 auto event_modifiers = mie::expand_modifiers(modifiers);
125 auto button_event = builder->pointer_event(event_time,117 auto button_event = builder->pointer_event(event_time,
126 event_modifiers,
127 action,118 action,
128 buttons,119 buttons,
129 pos.x.as_float(),120 pos.x.as_float(),
@@ -159,17 +150,15 @@
159150
160 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(151 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
161 std::chrono::system_clock::now().time_since_epoch());152 std::chrono::system_clock::now().time_since_epoch());
162 auto event_modifiers = mie::expand_modifiers(modifiers);
163 // constant scaling is used here to simplify checking for the153 // constant scaling is used here to simplify checking for the
164 // expected results. Default settings of the device lead to no154 // expected results. Default settings of the device lead to no
165 // scaling at all.155 // scaling at all.
166 auto acceleration = (settings.cursor_acceleration_bias + 1.0);156 auto acceleration = (settings.cursor_acceleration_bias + 1.0);
167 auto rel_x = pointer.rel_x * acceleration;157 auto rel_x = pointer.rel_x * acceleration;
168 auto rel_y = pointer.rel_y * acceleration;158 auto rel_y = pointer.rel_y * acceleration;
169 159
170 update_position(rel_x, rel_y);160 update_position(rel_x, rel_y);
171 auto pointer_event = builder->pointer_event(event_time,161 auto pointer_event = builder->pointer_event(event_time,
172 event_modifiers,
173 mir_pointer_action_motion,162 mir_pointer_action_motion,
174 buttons,163 buttons,
175 pos.x.as_float(),164 pos.x.as_float(),
@@ -195,9 +184,8 @@
195184
196 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(185 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
197 std::chrono::system_clock::now().time_since_epoch());186 std::chrono::system_clock::now().time_since_epoch());
198 auto event_modifiers = mie::expand_modifiers(modifiers);
199187
200 auto touch_event = builder->touch_event(event_time, event_modifiers);188 auto touch_event = builder->touch_event(event_time);
201189
202 auto touch_action = mir_touch_action_up;190 auto touch_action = mir_touch_action_up;
203 if (touch.action == synthesis::TouchParameters::Action::Tap)191 if (touch.action == synthesis::TouchParameters::Action::Tap)
204192
=== modified file 'tests/mir_test_framework/fake_input_device_impl.h'
--- tests/mir_test_framework/fake_input_device_impl.h 2015-10-23 16:32:32 +0000
+++ tests/mir_test_framework/fake_input_device_impl.h 2015-10-26 14:13:05 +0000
@@ -79,7 +79,6 @@
79 mir::input::EventBuilder* builder{nullptr};79 mir::input::EventBuilder* builder{nullptr};
80 mir::input::InputDeviceInfo info;80 mir::input::InputDeviceInfo info;
81 std::shared_ptr<mir::dispatch::Dispatchable> const queue;81 std::shared_ptr<mir::dispatch::Dispatchable> const queue;
82 uint32_t modifiers{0};
83 mir::geometry::Point pos, scroll;82 mir::geometry::Point pos, scroll;
84 MirPointerButtons buttons;83 MirPointerButtons buttons;
85 mir::input::PointerSettings settings;84 mir::input::PointerSettings settings;
8685
=== modified file 'tests/unit-tests/input/evdev/test_libinput_device.cpp'
--- tests/unit-tests/input/evdev/test_libinput_device.cpp 2015-10-23 16:32:32 +0000
+++ tests/unit-tests/input/evdev/test_libinput_device.cpp 2015-10-26 14:13:05 +0000
@@ -78,16 +78,15 @@
78 mi::DefaultEventBuilder builder{MirInputDeviceId{3}, cookie_factory};78 mi::DefaultEventBuilder builder{MirInputDeviceId{3}, cookie_factory};
79 MockEventBuilder()79 MockEventBuilder()
80 {80 {
81 ON_CALL(*this, key_event(_,_,_,_,_))81 ON_CALL(*this, key_event(_,_,_,_))
82 .WillByDefault(Invoke([this](Timestamp time, MirKeyboardAction action, xkb_keysym_t key, int scan_code,82 .WillByDefault(Invoke([this](Timestamp time, MirKeyboardAction action, xkb_keysym_t key, int scan_code)
83 MirInputEventModifiers modifier)
84 {83 {
85 return builder.key_event(time, action, key, scan_code, modifier);84 return builder.key_event(time, action, key, scan_code);
86 }));85 }));
87 ON_CALL(*this, touch_event(_,_))86 ON_CALL(*this, touch_event(_))
88 .WillByDefault(Invoke([this](Timestamp time, MirInputEventModifiers modifier)87 .WillByDefault(Invoke([this](Timestamp time)
89 {88 {
90 return builder.touch_event(time, modifier);89 return builder.touch_event(time);
91 }));90 }));
92 ON_CALL(*this, add_touch(_,_,_,_,_,_,_,_,_,_))91 ON_CALL(*this, add_touch(_,_,_,_,_,_,_,_,_,_))
93 .WillByDefault(Invoke([this](MirEvent& event, MirTouchId id, MirTouchAction action,92 .WillByDefault(Invoke([this](MirEvent& event, MirTouchId id, MirTouchAction action,
@@ -97,13 +96,12 @@
97 return builder.add_touch(event, id, action, tooltype, x, y, major, minor,96 return builder.add_touch(event, id, action, tooltype, x, y, major, minor,
98 pressure, size);97 pressure, size);
99 }));98 }));
100 ON_CALL(*this, pointer_event(_,_,_,_,_,_,_,_,_,_))99 ON_CALL(*this, pointer_event(_, _, _, _, _, _, _, _, _))
101 .WillByDefault(Invoke([this](Timestamp time, MirInputEventModifiers modifier, MirPointerAction action,100 .WillByDefault(Invoke([this](Timestamp time, MirPointerAction action, MirPointerButtons buttons, float x,
102 MirPointerButtons buttons, float x, float y, float hscroll, float vscroll,101 float y, float hscroll, float vscroll, float relative_x, float relative_y)
103 float relative_x, float relative_y)
104 {102 {
105 return builder.pointer_event(time, modifier, action, buttons, x, y, hscroll,103 return builder.pointer_event(time, action, buttons, x, y, hscroll, vscroll,
106 vscroll, relative_x, relative_y);104 relative_x, relative_y);
107 }));105 }));
108 ON_CALL(*this, configuration_event(_,_))106 ON_CALL(*this, configuration_event(_,_))
109 .WillByDefault(Invoke([this](Timestamp time, MirInputConfigurationAction action)107 .WillByDefault(Invoke([this](Timestamp time, MirInputConfigurationAction action)
@@ -112,14 +110,14 @@
112 }));110 }));
113 }111 }
114 using EventBuilder::Timestamp;112 using EventBuilder::Timestamp;
115 MOCK_METHOD5(key_event, mir::EventUPtr(Timestamp, MirKeyboardAction, xkb_keysym_t, int, MirInputEventModifiers));113 MOCK_METHOD4(key_event, mir::EventUPtr(Timestamp, MirKeyboardAction, xkb_keysym_t, int));
116114
117 MOCK_METHOD2(touch_event, mir::EventUPtr(Timestamp, MirInputEventModifiers));115 MOCK_METHOD1(touch_event, mir::EventUPtr(Timestamp));
118 MOCK_METHOD10(add_touch, void(MirEvent&, MirTouchId, MirTouchAction, MirTouchTooltype, float, float, float, float,116 MOCK_METHOD10(add_touch, void(MirEvent&, MirTouchId, MirTouchAction, MirTouchTooltype, float, float, float, float,
119 float, float));117 float, float));
120118
121 MOCK_METHOD10(pointer_event, mir::EventUPtr(Timestamp, MirInputEventModifiers, MirPointerAction, MirPointerButtons,119 MOCK_METHOD9(pointer_event, mir::EventUPtr(Timestamp, MirPointerAction, MirPointerButtons, float, float, float,
122 float, float, float, float, float, float));120 float, float, float));
123 MOCK_METHOD2(configuration_event, mir::EventUPtr(Timestamp, MirInputConfigurationAction));121 MOCK_METHOD2(configuration_event, mir::EventUPtr(Timestamp, MirInputConfigurationAction));
124};122};
125123
@@ -478,9 +476,9 @@
478 setup_key_event(fake_event_1, event_time_1, KEY_A, LIBINPUT_KEY_STATE_PRESSED);476 setup_key_event(fake_event_1, event_time_1, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
479 setup_key_event(fake_event_2, event_time_2, KEY_A, LIBINPUT_KEY_STATE_RELEASED);477 setup_key_event(fake_event_2, event_time_2, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
480478
481 EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_A, mir_input_event_modifier_none));479 EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_A));
482 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyDownEvent())));480 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyDownEvent())));
483 EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_up, _, KEY_A, mir_input_event_modifier_none));481 EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_up, _, KEY_A));
484 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyUpEvent())));482 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyUpEvent())));
485483
486 keyboard.start(&mock_sink, &mock_builder);484 keyboard.start(&mock_sink, &mock_builder);
@@ -495,15 +493,12 @@
495 setup_key_event(fake_event_3, event_time_3, KEY_C, LIBINPUT_KEY_STATE_RELEASED);493 setup_key_event(fake_event_3, event_time_3, KEY_C, LIBINPUT_KEY_STATE_RELEASED);
496494
497 InSequence seq;495 InSequence seq;
498 EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_C, mir_input_event_modifier_none));496 EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_C));
499 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),mt::KeyDownEvent())));497 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),mt::KeyDownEvent())));
500 EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_down, _, KEY_LEFTALT, mir_input_event_modifier_none));498 EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_down, _, KEY_LEFTALT));
501 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_LEFTALT),mt::KeyDownEvent())));499 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_LEFTALT),mt::KeyDownEvent())));
502 EXPECT_CALL(mock_builder, key_event(time_stamp_3, mir_keyboard_action_up, _, KEY_C,500 EXPECT_CALL(mock_builder, key_event(time_stamp_3, mir_keyboard_action_up, _, KEY_C));
503 mir_input_event_modifier_alt | mir_input_event_modifier_alt_left));
504 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),501 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),
505 mt::KeyWithModifiers(MirInputEventModifiers{
506 mir_input_event_modifier_alt | mir_input_event_modifier_alt_left}),
507 mt::KeyUpEvent())));502 mt::KeyUpEvent())));
508503
509 keyboard.start(&mock_sink, &mock_builder);504 keyboard.start(&mock_sink, &mock_builder);
@@ -583,11 +578,11 @@
583578
584 InSequence seq;579 InSequence seq;
585 // expect two scroll events..580 // expect two scroll events..
586 EXPECT_CALL(mock_builder, pointer_event(time_stamp_1, mir_input_event_modifier_none, mir_pointer_action_motion, 0,581 EXPECT_CALL(mock_builder,
587 0.0f, 0.0f, 0.0f, 20.0f, 0.0f, 0.0f));582 pointer_event(time_stamp_1, mir_pointer_action_motion, 0, 0.0f, 0.0f, 0.0f, 20.0f, 0.0f, 0.0f));
588 EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_vscroll, 20.0f)));583 EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_vscroll, 20.0f)));
589 EXPECT_CALL(mock_builder, pointer_event(time_stamp_2, mir_input_event_modifier_none, mir_pointer_action_motion, 0,584 EXPECT_CALL(mock_builder,
590 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f));585 pointer_event(time_stamp_2, mir_pointer_action_motion, 0, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f));
591 EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_hscroll, 5.0f)));586 EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_hscroll, 5.0f)));
592587
593 mouse.start(&mock_sink, &mock_builder);588 mouse.start(&mock_sink, &mock_builder);
@@ -608,7 +603,7 @@
608 setup_touch_frame(fake_event_2);603 setup_touch_frame(fake_event_2);
609604
610 InSequence seq;605 InSequence seq;
611 EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));606 EXPECT_CALL(mock_builder, touch_event(time_stamp_1));
612 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,607 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,
613 pressure, major, minor, major));608 pressure, major, minor, major));
614 EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x, y)));609 EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x, y)));
@@ -631,7 +626,7 @@
631 setup_touch_frame(fake_event_2);626 setup_touch_frame(fake_event_2);
632627
633 InSequence seq;628 InSequence seq;
634 EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));629 EXPECT_CALL(mock_builder, touch_event(time_stamp_1));
635 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_change, mir_touch_tooltype_finger, x, y,630 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_change, mir_touch_tooltype_finger, x, y,
636 pressure, major, minor, major));631 pressure, major, minor, major));
637 EXPECT_CALL(mock_sink, handle_input(mt::TouchMovementEvent()));632 EXPECT_CALL(mock_sink, handle_input(mt::TouchMovementEvent()));
@@ -656,12 +651,12 @@
656 setup_touch_frame(fake_event_4);651 setup_touch_frame(fake_event_4);
657652
658 InSequence seq;653 InSequence seq;
659 EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));654 EXPECT_CALL(mock_builder, touch_event(time_stamp_1));
660 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,655 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,
661 pressure, major, minor, major));656 pressure, major, minor, major));
662 EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x, y)));657 EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x, y)));
663658
664 EXPECT_CALL(mock_builder, touch_event(time_stamp_2, mir_input_event_modifier_none));659 EXPECT_CALL(mock_builder, touch_event(time_stamp_2));
665 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_up, mir_touch_tooltype_finger, x, y,660 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_up, mir_touch_tooltype_finger, x, y,
666 pressure, major, minor, major));661 pressure, major, minor, major));
667 EXPECT_CALL(mock_sink, handle_input(mt::TouchUpEvent(x, y)));662 EXPECT_CALL(mock_sink, handle_input(mt::TouchUpEvent(x, y)));
668663
=== modified file 'tests/unit-tests/input/test_default_input_device_hub.cpp'
--- tests/unit-tests/input/test_default_input_device_hub.cpp 2015-10-23 16:32:32 +0000
+++ tests/unit-tests/input/test_default_input_device_hub.cpp 2015-10-26 14:13:05 +0000
@@ -274,7 +274,7 @@
274 observer_loop.trigger_server_actions();274 observer_loop.trigger_server_actions();
275275
276 auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0,276 auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0,
277 KEY_A, mir_input_event_modifier_none);277 KEY_A);
278278
279 EXPECT_CALL(mock_dispatcher, dispatch(AllOf(mt::InputDeviceIdMatches(handle->id()), mt::MirKeyEventMatches(event.get()))));279 EXPECT_CALL(mock_dispatcher, dispatch(AllOf(mt::InputDeviceIdMatches(handle->id()), mt::MirKeyEventMatches(event.get()))));
280280
@@ -293,23 +293,23 @@
293293
294 observer_loop.trigger_server_actions();294 observer_loop.trigger_server_actions();
295295
296 auto touch_event_1 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);296 auto touch_event_1 = builder->touch_event(arbitrary_timestamp);
297 builder->add_touch(*touch_event_1, 0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f,297 builder->add_touch(*touch_event_1, 0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f,
298 5.0f, 4.0f);298 5.0f, 4.0f);
299299
300 auto touch_event_2 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);300 auto touch_event_2 = builder->touch_event(arbitrary_timestamp);
301 builder->add_touch(*touch_event_2, 0, mir_touch_action_change, mir_touch_tooltype_finger, 24.0f, 34.0f, 50.0f,301 builder->add_touch(*touch_event_2, 0, mir_touch_action_change, mir_touch_tooltype_finger, 24.0f, 34.0f, 50.0f,
302 15.0f, 5.0f, 4.0f);302 15.0f, 5.0f, 4.0f);
303 builder->add_touch(*touch_event_2, 1, mir_touch_action_down, mir_touch_tooltype_finger, 60.0f, 34.0f, 50.0f, 15.0f,303 builder->add_touch(*touch_event_2, 1, mir_touch_action_down, mir_touch_tooltype_finger, 60.0f, 34.0f, 50.0f, 15.0f,
304 5.0f, 4.0f);304 5.0f, 4.0f);
305305
306 auto touch_event_3 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);306 auto touch_event_3 = builder->touch_event(arbitrary_timestamp);
307 builder->add_touch(*touch_event_3, 0, mir_touch_action_up, mir_touch_tooltype_finger, 24.0f, 34.0f, 50.0f, 15.0f,307 builder->add_touch(*touch_event_3, 0, mir_touch_action_up, mir_touch_tooltype_finger, 24.0f, 34.0f, 50.0f, 15.0f,
308 5.0f, 4.0f);308 5.0f, 4.0f);
309 builder->add_touch(*touch_event_3, 1, mir_touch_action_change, mir_touch_tooltype_finger, 70.0f, 30.0f, 50.0f,309 builder->add_touch(*touch_event_3, 1, mir_touch_action_change, mir_touch_tooltype_finger, 70.0f, 30.0f, 50.0f,
310 15.0f, 5.0f, 4.0f);310 15.0f, 5.0f, 4.0f);
311311
312 auto touch_event_4 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);312 auto touch_event_4 = builder->touch_event(arbitrary_timestamp);
313 builder->add_touch(*touch_event_4, 1, mir_touch_action_up, mir_touch_tooltype_finger, 70.0f, 35.0f, 50.0f, 15.0f,313 builder->add_touch(*touch_event_4, 1, mir_touch_action_up, mir_touch_tooltype_finger, 70.0f, 35.0f, 50.0f, 15.0f,
314 5.0f, 4.0f);314 5.0f, 4.0f);
315315
@@ -378,17 +378,149 @@
378 using namespace ::testing;378 using namespace ::testing;
379379
380 auto x = 12.2f, y = 14.3f;380 auto x = 12.2f, y = 14.3f;
381 auto const mac = 0;381
382382 mi::InputSink* sink;
383 auto event = mir::events::make_event(0, 0ns, mac, mir_input_event_modifier_none, mir_pointer_action_motion, 0,383 mi::EventBuilder* builder;
384 x, y, 0.0f, 0.0f, 0.0f, 0.0f);384 capture_input_sink(device, sink, builder);
385 hub.add_device(mt::fake_shared(device));
386
387 auto event = builder->pointer_event(0ns, mir_pointer_action_motion, 0, x, y, 0.0f, 0.0f, 0.0f, 0.0f);
385388
386 EXPECT_CALL(mock_cursor_listener, cursor_moved_to(x, y)).Times(1);389 EXPECT_CALL(mock_cursor_listener, cursor_moved_to(x, y)).Times(1);
387390
388 mi::InputSink* sink;
389 mi::EventBuilder* builder;
390 capture_input_sink(device, sink, builder);
391 hub.add_device(mt::fake_shared(device));
392
393 sink->handle_input(*event);391 sink->handle_input(*event);
394}392}
393
394TEST_F(InputDeviceHubTest, input_sink_tracks_modifier)
395{
396 using namespace ::testing;
397
398 mi::InputSink* key_board_sink;
399 mi::EventBuilder* key_event_builder;
400 std::shared_ptr<mi::Device> key_handle;
401
402 capture_input_sink(device, key_board_sink, key_event_builder);
403
404 InSequence seq;
405 EXPECT_CALL(mock_observer,device_added(_))
406 .WillOnce(SaveArg<0>(&key_handle));
407
408 hub.add_observer(mt::fake_shared(mock_observer));
409 hub.add_device(mt::fake_shared(device));
410
411 observer_loop.trigger_server_actions();
412
413 const MirInputEventModifiers shift_left = mir_input_event_modifier_shift_left | mir_input_event_modifier_shift;
414 auto shift_down =
415 key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTSHIFT);
416 auto shift_up =
417 key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTSHIFT);
418
419 EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(shift_left)));
420 EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(mir_input_event_modifier_none)));
421
422 key_board_sink->handle_input(*shift_down);
423 key_board_sink->handle_input(*shift_up);
424}
425
426TEST_F(InputDeviceHubTest, input_sink_unifies_modifier_state_accross_devices)
427{
428 using namespace ::testing;
429
430 mi::InputSink* mouse_sink;
431 mi::EventBuilder* mouse_event_builder;
432 mi::InputSink* key_board_sink;
433 mi::EventBuilder* key_event_builder;
434 std::shared_ptr<mi::Device> mouse_handle;
435 std::shared_ptr<mi::Device> key_handle;
436
437 capture_input_sink(device, mouse_sink, mouse_event_builder);
438 capture_input_sink(another_device, key_board_sink, key_event_builder);
439
440 InSequence seq;
441 EXPECT_CALL(mock_observer,device_added(_))
442 .WillOnce(SaveArg<0>(&mouse_handle));
443 EXPECT_CALL(mock_observer,device_added(_))
444 .WillOnce(SaveArg<0>(&key_handle));
445
446 hub.add_observer(mt::fake_shared(mock_observer));
447 hub.add_device(mt::fake_shared(device));
448 hub.add_device(mt::fake_shared(another_device));
449
450 observer_loop.trigger_server_actions();
451
452 const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt;
453 auto key =
454 key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);
455 auto motion =
456 mouse_event_builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 12, 40, 0, 0, 12, 40);
457
458 EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(r_alt_modifier)));
459 EXPECT_CALL(mock_dispatcher, dispatch(mt::PointerEventWithModifiers(r_alt_modifier)));
460
461 key_board_sink->handle_input(*key);
462 mouse_sink->handle_input(*motion);
463
464 EXPECT_THAT(key_handle->id(), Ne(mouse_handle->id()));
465}
466
467TEST_F(InputDeviceHubTest, input_sink_reduces_modifier_state_accross_devices)
468{
469 using namespace ::testing;
470
471 mi::InputSink* mouse_sink;
472 mi::EventBuilder* mouse_event_builder;
473 mi::InputSink* key_board_sink_1;
474 mi::EventBuilder* key_event_builder_1;
475 mi::InputSink* key_board_sink_2;
476 mi::EventBuilder* key_event_builder_2;
477 std::shared_ptr<mi::Device> mouse_handle;
478 std::shared_ptr<mi::Device> key_handle_1;
479 std::shared_ptr<mi::Device> key_handle_2;
480
481 capture_input_sink(device, mouse_sink, mouse_event_builder);
482 capture_input_sink(another_device, key_board_sink_1, key_event_builder_1);
483 capture_input_sink(third_device, key_board_sink_2, key_event_builder_2);
484
485 InSequence seq;
486 EXPECT_CALL(mock_observer, device_added(_))
487 .WillOnce(SaveArg<0>(&mouse_handle));
488 EXPECT_CALL(mock_observer, device_added(_))
489 .WillOnce(SaveArg<0>(&key_handle_1));
490 EXPECT_CALL(mock_observer, device_added(_))
491 .WillOnce(SaveArg<0>(&key_handle_2));
492
493 hub.add_observer(mt::fake_shared(mock_observer));
494 hub.add_device(mt::fake_shared(device));
495 hub.add_device(mt::fake_shared(another_device));
496 hub.add_device(mt::fake_shared(third_device));
497
498 const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt;
499 const MirInputEventModifiers l_ctrl_modifier = mir_input_event_modifier_ctrl_left | mir_input_event_modifier_ctrl;
500 const MirInputEventModifiers combined_modifier = r_alt_modifier | l_ctrl_modifier;
501
502 observer_loop.trigger_server_actions();
503
504 auto alt_down = key_event_builder_1->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);
505 auto ctrl_down = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTCTRL);
506 auto ctrl_up = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTCTRL);
507
508 auto motion_1 =
509 mouse_event_builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 12, 40, 0, 0, 12, 40);
510 auto motion_2 =
511 mouse_event_builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 30, 50, 0, 0, 18, 10);
512
513 EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(r_alt_modifier)));
514 EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(l_ctrl_modifier)));
515 EXPECT_CALL(mock_dispatcher, dispatch(mt::PointerEventWithModifiers(combined_modifier)));
516 EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(mir_input_event_modifier_none)));
517 EXPECT_CALL(mock_dispatcher, dispatch(mt::PointerEventWithModifiers(r_alt_modifier)));
518
519 key_board_sink_1->handle_input(*alt_down);
520 key_board_sink_2->handle_input(*ctrl_down);
521 mouse_sink->handle_input(*motion_1);
522 key_board_sink_2->handle_input(*ctrl_up);
523 mouse_sink->handle_input(*motion_2);
524
525 EXPECT_THAT(key_handle_1->id(), Ne(key_handle_2->id()));
526}

Subscribers

People subscribed via source and target branches