~ubuntu-branches/ubuntu/wily/mir/wily-proposed

« back to all changes in this revision

Viewing changes to tests/unit-tests/input/evdev/test_libinput_device.cpp

  • Committer: Package Import Robot
  • Author(s): Alexandros Frantzis
  • Date: 2015-10-08 16:12:19 UTC
  • mto: This revision was merged to the branch mainline in revision 109.
  • Revision ID: package-import@ubuntu.com-20151008161219-emk4a1ys51yy0wjb
Tags: upstream-0.17.0+15.10.20151008.2
ImportĀ upstreamĀ versionĀ 0.17.0+15.10.20151008.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "src/platforms/evdev/libinput_device.h"
 
20
#include "src/server/report/null_report_factory.h"
 
21
#include "src/server/input/default_event_builder.h"
 
22
 
 
23
#include "mir/input/input_device_registry.h"
 
24
#include "mir/input/input_sink.h"
 
25
#include "mir/geometry/point.h"
 
26
#include "mir/geometry/rectangle.h"
 
27
#include "mir/test/event_matchers.h"
 
28
#include "mir/test/doubles/mock_libinput.h"
 
29
#include "mir/test/gmock_fixes.h"
 
30
#include "mir_test_framework/udev_environment.h"
 
31
 
 
32
#include <gmock/gmock.h>
 
33
#include <gtest/gtest.h>
 
34
#include <linux/input.h>
 
35
 
 
36
#include <chrono>
 
37
 
 
38
namespace mi = mir::input;
 
39
namespace mie = mi::evdev;
 
40
namespace mt = mir::test;
 
41
namespace mtf = mir_test_framework;
 
42
namespace mtd = mt::doubles;
 
43
namespace geom = mir::geometry;
 
44
 
 
45
namespace
 
46
{
 
47
 
 
48
class StubInputDeviceRegistry : public mi::InputDeviceRegistry
 
49
{
 
50
public:
 
51
    void add_device(std::shared_ptr<mi::InputDevice> const&) override {}
 
52
    void remove_device(std::shared_ptr<mi::InputDevice> const&) override {}
 
53
};
 
54
 
 
55
using namespace ::testing;
 
56
 
 
57
struct MockInputSink : mi::InputSink
 
58
{
 
59
    MockInputSink()
 
60
    {
 
61
        ON_CALL(*this, bounding_rectangle())
 
62
            .WillByDefault(Return(geom::Rectangle({0,0}, {100,100})));
 
63
    }
 
64
    MOCK_METHOD1(handle_input,void(MirEvent &));
 
65
    MOCK_METHOD1(confine_pointer, void(geom::Point&));
 
66
    MOCK_CONST_METHOD0(bounding_rectangle, geom::Rectangle());
 
67
};
 
68
 
 
69
struct MockEventBuilder : mi::EventBuilder
 
70
{
 
71
    mi::DefaultEventBuilder builder{MirInputDeviceId{3}};
 
72
    MockEventBuilder()
 
73
    {
 
74
        ON_CALL(*this, key_event(_,_,_,_,_))
 
75
            .WillByDefault(Invoke([this](Timestamp time, MirKeyboardAction action, xkb_keysym_t key, int scan_code,
 
76
                                         MirInputEventModifiers modifier)
 
77
                                  {
 
78
                                        return builder.key_event(time, action, key, scan_code, modifier);
 
79
                                  }));
 
80
        ON_CALL(*this, touch_event(_,_))
 
81
            .WillByDefault(Invoke([this](Timestamp time, MirInputEventModifiers modifier)
 
82
                                  {
 
83
                                        return builder.touch_event(time, modifier);
 
84
                                  }));
 
85
        ON_CALL(*this, add_touch(_,_,_,_,_,_,_,_,_,_))
 
86
            .WillByDefault(Invoke([this](MirEvent& event, MirTouchId id, MirTouchAction action,
 
87
                                         MirTouchTooltype tooltype, float x, float y, float major, float minor,
 
88
                                         float pressure, float size)
 
89
                                  {
 
90
                                        return builder.add_touch(event, id, action, tooltype, x, y, major, minor,
 
91
                                                                 pressure, size);
 
92
                                  }));
 
93
        ON_CALL(*this, pointer_event(_,_,_,_,_,_,_,_,_,_))
 
94
            .WillByDefault(Invoke([this](Timestamp time, MirInputEventModifiers modifier, MirPointerAction action,
 
95
                                         MirPointerButtons buttons, float x, float y, float hscroll, float vscroll,
 
96
                                         float relative_x, float relative_y)
 
97
                                  {
 
98
                                      return builder.pointer_event(time, modifier, action, buttons, x, y, hscroll,
 
99
                                                                   vscroll, relative_x, relative_y);
 
100
                                  }));
 
101
        ON_CALL(*this, configuration_event(_,_))
 
102
            .WillByDefault(Invoke([this](Timestamp time, MirInputConfigurationAction action)
 
103
                                  {
 
104
                                        return builder.configuration_event(time, action);
 
105
                                  }));
 
106
    }
 
107
    using EventBuilder::Timestamp;
 
108
    MOCK_METHOD5(key_event, mir::EventUPtr(Timestamp, MirKeyboardAction, xkb_keysym_t, int, MirInputEventModifiers));
 
109
 
 
110
    MOCK_METHOD2(touch_event, mir::EventUPtr(Timestamp, MirInputEventModifiers));
 
111
    MOCK_METHOD10(add_touch, void(MirEvent&, MirTouchId, MirTouchAction, MirTouchTooltype, float, float, float, float,
 
112
                                  float, float));
 
113
 
 
114
    MOCK_METHOD10(pointer_event, mir::EventUPtr(Timestamp, MirInputEventModifiers, MirPointerAction, MirPointerButtons,
 
115
                                                float, float, float, float, float, float));
 
116
    MOCK_METHOD2(configuration_event, mir::EventUPtr(Timestamp, MirInputConfigurationAction));
 
117
};
 
118
 
 
119
struct LibInputDevice : public ::testing::Test
 
120
{
 
121
    mtf::UdevEnvironment env;
 
122
    ::testing::NiceMock<mir::test::doubles::MockLibInput> mock_libinput;
 
123
    ::testing::NiceMock<MockInputSink> mock_sink;
 
124
    ::testing::NiceMock<MockEventBuilder> mock_builder;
 
125
 
 
126
    libinput* fake_input = reinterpret_cast<libinput*>(0xF4C3);
 
127
    libinput_device* fake_device = reinterpret_cast<libinput_device*>(0xF4C4);
 
128
    libinput_event* fake_event_1 = reinterpret_cast<libinput_event*>(0xF4C5);
 
129
    libinput_event* fake_event_2 = reinterpret_cast<libinput_event*>(0xF4C6);
 
130
    libinput_event* fake_event_3 = reinterpret_cast<libinput_event*>(0xF4C7);
 
131
    libinput_event* fake_event_4 = reinterpret_cast<libinput_event*>(0xF4C8);
 
132
    libinput_device* second_fake_device = reinterpret_cast<libinput_device*>(0xF4C9);
 
133
 
 
134
    const uint64_t event_time_1 = 1000;
 
135
    const mi::EventBuilder::Timestamp time_stamp_1{std::chrono::microseconds{event_time_1}};
 
136
    const uint64_t event_time_2 = 2000;
 
137
    const mi::EventBuilder::Timestamp time_stamp_2{std::chrono::microseconds{event_time_2}};
 
138
    const uint64_t event_time_3 = 3000;
 
139
    const mi::EventBuilder::Timestamp time_stamp_3{std::chrono::microseconds{event_time_3}};
 
140
    const uint64_t event_time_4 = 4000;
 
141
    const mi::EventBuilder::Timestamp time_stamp_4{std::chrono::microseconds{event_time_4}};
 
142
 
 
143
    char const* laptop_keyboard_device_path = "/dev/input/event4";
 
144
    char const* path{laptop_keyboard_device_path};
 
145
 
 
146
    LibInputDevice()
 
147
    {
 
148
        setup_device(fake_device, path, "laptop-keyboard", 5252, 3113);
 
149
 
 
150
        ON_CALL(mock_libinput, libinput_path_create_context(_,_))
 
151
            .WillByDefault(Return(fake_input));
 
152
    }
 
153
 
 
154
    void setup_device(libinput_device* dev, char const* device_path, char const* umock_name, unsigned int vendor_id, unsigned int product_id)
 
155
    {
 
156
        env.add_standard_device(umock_name);
 
157
        mock_libinput.setup_device(fake_input, dev, device_path, umock_name, vendor_id, product_id);
 
158
    }
 
159
 
 
160
    void setup_pointer_configuration(libinput_device* dev, double accel_speed, MirPointerButton primary)
 
161
    {
 
162
        EXPECT_CALL(mock_libinput, libinput_device_config_accel_get_speed(dev))
 
163
            .WillRepeatedly(Return(accel_speed));
 
164
        EXPECT_CALL(mock_libinput, libinput_device_config_left_handed_get(dev))
 
165
            .WillRepeatedly(Return(primary == mir_pointer_button_secondary));
 
166
    }
 
167
 
 
168
    void setup_key_event(libinput_event* event, uint64_t event_time, uint32_t key, libinput_key_state state)
 
169
    {
 
170
        auto key_event = reinterpret_cast<libinput_event_keyboard*>(event);
 
171
 
 
172
        EXPECT_CALL(mock_libinput, libinput_event_get_type(event))
 
173
            .WillRepeatedly(Return(LIBINPUT_EVENT_KEYBOARD_KEY));
 
174
        EXPECT_CALL(mock_libinput, libinput_event_get_keyboard_event(event))
 
175
            .WillRepeatedly(Return(key_event));
 
176
        EXPECT_CALL(mock_libinput, libinput_event_keyboard_get_time_usec(key_event))
 
177
            .WillRepeatedly(Return(event_time));
 
178
        EXPECT_CALL(mock_libinput, libinput_event_keyboard_get_key(key_event))
 
179
            .WillRepeatedly(Return(key));
 
180
        EXPECT_CALL(mock_libinput, libinput_event_keyboard_get_key_state(key_event))
 
181
            .WillRepeatedly(Return(state));
 
182
    }
 
183
 
 
184
    void setup_pointer_event(libinput_event* event, uint64_t event_time, float relatve_x, float relatve_y)
 
185
    {
 
186
        auto pointer_event = reinterpret_cast<libinput_event_pointer*>(event);
 
187
 
 
188
        EXPECT_CALL(mock_libinput, libinput_event_get_type(event))
 
189
            .WillRepeatedly(Return(LIBINPUT_EVENT_POINTER_MOTION));
 
190
        EXPECT_CALL(mock_libinput, libinput_event_get_pointer_event(event))
 
191
            .WillRepeatedly(Return(pointer_event));
 
192
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_time_usec(pointer_event))
 
193
            .WillRepeatedly(Return(event_time));
 
194
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_dx(pointer_event))
 
195
            .WillRepeatedly(Return(relatve_x));
 
196
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_dy(pointer_event))
 
197
            .WillRepeatedly(Return(relatve_y));
 
198
    }
 
199
 
 
200
    void setup_button_event(libinput_event* event, uint64_t event_time, int button, libinput_button_state state)
 
201
    {
 
202
        auto pointer_event = reinterpret_cast<libinput_event_pointer*>(event);
 
203
 
 
204
        EXPECT_CALL(mock_libinput, libinput_event_get_type(event))
 
205
            .WillRepeatedly(Return(LIBINPUT_EVENT_POINTER_BUTTON));
 
206
        EXPECT_CALL(mock_libinput, libinput_event_get_pointer_event(event))
 
207
            .WillRepeatedly(Return(pointer_event));
 
208
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_time_usec(pointer_event))
 
209
            .WillRepeatedly(Return(event_time));
 
210
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_button(pointer_event))
 
211
            .WillRepeatedly(Return(button));
 
212
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_button_state(pointer_event))
 
213
            .WillRepeatedly(Return(state));
 
214
    }
 
215
 
 
216
    void setup_axis_event(libinput_event* event, uint64_t event_time, double horizontal, double vertical)
 
217
    {
 
218
        auto pointer_event = reinterpret_cast<libinput_event_pointer*>(event);
 
219
 
 
220
        EXPECT_CALL(mock_libinput, libinput_event_get_type(event))
 
221
            .WillRepeatedly(Return(LIBINPUT_EVENT_POINTER_AXIS));
 
222
        EXPECT_CALL(mock_libinput, libinput_event_get_pointer_event(event))
 
223
            .WillRepeatedly(Return(pointer_event));
 
224
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_time_usec(pointer_event))
 
225
            .WillRepeatedly(Return(event_time));
 
226
        EXPECT_CALL(mock_libinput, libinput_event_pointer_has_axis(pointer_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
 
227
            .WillRepeatedly(Return(horizontal!=0.0));
 
228
        EXPECT_CALL(mock_libinput, libinput_event_pointer_has_axis(pointer_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
 
229
            .WillRepeatedly(Return(vertical!=0.0));
 
230
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_axis_value(pointer_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
 
231
            .WillRepeatedly(Return(vertical));
 
232
        EXPECT_CALL(mock_libinput, libinput_event_pointer_get_axis_value(pointer_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
 
233
            .WillRepeatedly(Return(horizontal));
 
234
    }
 
235
 
 
236
    void setup_touch_event(libinput_event* event, libinput_event_type type, uint64_t event_time, int slot, float x,
 
237
                           float y, float major, float minor, float pressure)
 
238
    {
 
239
        auto touch_event = reinterpret_cast<libinput_event_touch*>(event);
 
240
 
 
241
        EXPECT_CALL(mock_libinput, libinput_event_get_type(event))
 
242
            .WillRepeatedly(Return(type));
 
243
        EXPECT_CALL(mock_libinput, libinput_event_get_touch_event(event))
 
244
            .WillRepeatedly(Return(touch_event));
 
245
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_slot(touch_event))
 
246
            .WillRepeatedly(Return(slot));
 
247
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_x_transformed(touch_event, _))
 
248
            .WillRepeatedly(Return(x));
 
249
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_y_transformed(touch_event, _))
 
250
            .WillRepeatedly(Return(y));
 
251
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_time_usec(touch_event))
 
252
            .WillRepeatedly(Return(event_time));
 
253
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_major_transformed(touch_event, _, _))
 
254
            .WillRepeatedly(Return(major));
 
255
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_minor_transformed(touch_event, _, _))
 
256
            .WillRepeatedly(Return(minor));
 
257
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_pressure(touch_event))
 
258
            .WillRepeatedly(Return(pressure));
 
259
    }
 
260
 
 
261
    void setup_touch_up_event(libinput_event* event, uint64_t event_time, int slot)
 
262
    {
 
263
        auto touch_event = reinterpret_cast<libinput_event_touch*>(event);
 
264
 
 
265
        EXPECT_CALL(mock_libinput, libinput_event_get_type(event))
 
266
            .WillRepeatedly(Return(LIBINPUT_EVENT_TOUCH_UP));
 
267
        EXPECT_CALL(mock_libinput, libinput_event_get_touch_event(event))
 
268
            .WillRepeatedly(Return(touch_event));
 
269
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_slot(touch_event))
 
270
            .WillRepeatedly(Return(slot));
 
271
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_x_transformed(touch_event, _))
 
272
            .Times(0);
 
273
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_y_transformed(touch_event, _))
 
274
            .Times(0);
 
275
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_x(touch_event))
 
276
            .Times(0);
 
277
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_y(touch_event))
 
278
            .Times(0);
 
279
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_time_usec(touch_event))
 
280
            .WillRepeatedly(Return(event_time));
 
281
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_major_transformed(touch_event, _, _))
 
282
            .Times(0);
 
283
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_minor_transformed(touch_event, _, _))
 
284
            .Times(0);
 
285
        EXPECT_CALL(mock_libinput, libinput_event_touch_get_pressure(touch_event))
 
286
            .Times(0);
 
287
 
 
288
    }
 
289
 
 
290
    void setup_touch_frame(libinput_event* event)
 
291
    {
 
292
        EXPECT_CALL(mock_libinput, libinput_event_get_type(event))
 
293
            .WillRepeatedly(Return(LIBINPUT_EVENT_TOUCH_FRAME));
 
294
    }
 
295
};
 
296
 
 
297
}
 
298
 
 
299
TEST_F(LibInputDevice, start_creates_and_unrefs_libinput_device_from_path)
 
300
{
 
301
    EXPECT_CALL(mock_libinput, libinput_path_add_device(fake_input,StrEq(path)))
 
302
        .Times(1);
 
303
    // according to manual libinput_path_add_device creates a temporary device with a ref count 0.
 
304
    // hence it needs a manual ref call
 
305
    EXPECT_CALL(mock_libinput, libinput_device_ref(fake_device))
 
306
        .Times(1);
 
307
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
308
    mie::LibInputDevice dev(mir::report::null_input_report(),
 
309
                            path,
 
310
                            std::move(mie::make_libinput_device(lib.get(), path)));
 
311
    dev.start(&mock_sink, &mock_builder);
 
312
}
 
313
 
 
314
TEST_F(LibInputDevice, open_device_of_group)
 
315
{
 
316
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
317
    char const* second_dev = "/dev/input/event13";
 
318
    char const* second_umock_dev_name = "bluetooth-magic-trackpad";
 
319
    
 
320
    setup_device(second_fake_device, second_dev, second_umock_dev_name, 9663, 1234);
 
321
 
 
322
    InSequence seq;
 
323
    EXPECT_CALL(mock_libinput, libinput_path_add_device(fake_input,StrEq(path))).Times(1);
 
324
    // according to manual libinput_path_add_device creates a temporary device with a ref count 0.
 
325
    // hence it needs a manual ref call
 
326
    EXPECT_CALL(mock_libinput, libinput_device_ref(fake_device)).Times(1);
 
327
    EXPECT_CALL(mock_libinput, libinput_path_add_device(fake_input,StrEq(second_dev))).Times(1);
 
328
    EXPECT_CALL(mock_libinput, libinput_device_ref(second_fake_device)).Times(1);
 
329
 
 
330
    mie::LibInputDevice dev(mir::report::null_input_report(),
 
331
                            path,
 
332
                            std::move(mie::make_libinput_device(lib.get(), path)));
 
333
    dev.add_device_of_group(second_dev, mie::make_libinput_device(lib.get(), second_dev));
 
334
    dev.start(&mock_sink, &mock_builder);
 
335
}
 
336
 
 
337
TEST_F(LibInputDevice, input_info_combines_capabilities)
 
338
{
 
339
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
340
    char const* second_dev = "/dev/input/event13";
 
341
    char const* second_umock_dev_name = "bluetooth-magic-trackpad";
 
342
    
 
343
    setup_device(second_fake_device, second_dev, second_umock_dev_name, 9663, 1234);
 
344
 
 
345
    mie::LibInputDevice dev(mir::report::null_input_report(),
 
346
                            path,
 
347
                            mie::make_libinput_device(lib.get(), path));
 
348
    dev.add_device_of_group(second_dev, mie::make_libinput_device(lib.get(), second_dev));
 
349
    auto info = dev.get_device_info();
 
350
 
 
351
    EXPECT_THAT(info.capabilities, Eq(mi::DeviceCapability::touchpad|
 
352
                                      mi::DeviceCapability::keyboard|
 
353
                                      mi::DeviceCapability::alpha_numeric));
 
354
}
 
355
 
 
356
TEST_F(LibInputDevice, removal_unrefs_libinput_device)
 
357
{
 
358
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
359
 
 
360
    EXPECT_CALL(mock_libinput, libinput_device_unref(fake_device))
 
361
        .Times(1);
 
362
 
 
363
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
364
}
 
365
 
 
366
 
 
367
TEST_F(LibInputDevice, process_event_converts_key_event)
 
368
{
 
369
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
370
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
371
 
 
372
    setup_key_event(fake_event_1, event_time_1, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
 
373
    setup_key_event(fake_event_2, event_time_2, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
 
374
 
 
375
    EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_A, mir_input_event_modifier_none));
 
376
    EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyDownEvent())));
 
377
    EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_up, _, KEY_A, mir_input_event_modifier_none));
 
378
    EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyUpEvent())));
 
379
 
 
380
    dev.start(&mock_sink, &mock_builder);
 
381
    dev.process_event(fake_event_1);
 
382
    dev.process_event(fake_event_2);
 
383
}
 
384
 
 
385
TEST_F(LibInputDevice, process_event_accumulates_key_state)
 
386
{
 
387
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
388
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
389
 
 
390
 
 
391
    setup_key_event(fake_event_1, event_time_1, KEY_C, LIBINPUT_KEY_STATE_PRESSED);
 
392
    setup_key_event(fake_event_2, event_time_2, KEY_LEFTALT, LIBINPUT_KEY_STATE_PRESSED);
 
393
    setup_key_event(fake_event_3, event_time_3, KEY_C, LIBINPUT_KEY_STATE_RELEASED);
 
394
 
 
395
    InSequence seq;
 
396
    EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_C, mir_input_event_modifier_none));
 
397
    EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),mt::KeyDownEvent())));
 
398
    EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_down, _, KEY_LEFTALT, mir_input_event_modifier_none));
 
399
    EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_LEFTALT),mt::KeyDownEvent())));
 
400
    EXPECT_CALL(mock_builder, key_event(time_stamp_3, mir_keyboard_action_up, _, KEY_C, mir_input_event_modifier_alt|mir_input_event_modifier_alt_left));
 
401
    EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),
 
402
                                              mt::KeyWithModifiers(
 
403
                                                  MirInputEventModifiers{
 
404
                                                      mir_input_event_modifier_alt|
 
405
                                                      mir_input_event_modifier_alt_left
 
406
                                                  }),
 
407
                                              mt::KeyUpEvent())));
 
408
 
 
409
    dev.start(&mock_sink, &mock_builder);
 
410
    dev.process_event(fake_event_1);
 
411
    dev.process_event(fake_event_2);
 
412
    dev.process_event(fake_event_3);
 
413
}
 
414
 
 
415
TEST_F(LibInputDevice, process_event_converts_pointer_event)
 
416
{
 
417
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
418
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
419
 
 
420
    float x = 15;
 
421
    float y = 17;
 
422
    setup_pointer_event(fake_event_1, event_time_1, x, y);
 
423
 
 
424
    EXPECT_CALL(mock_sink, handle_input(mt::PointerEventWithPosition(x,y)));
 
425
 
 
426
    dev.start(&mock_sink, &mock_builder);
 
427
    dev.process_event(fake_event_1);
 
428
}
 
429
 
 
430
TEST_F(LibInputDevice, process_event_provides_relative_coordinates)
 
431
{
 
432
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
433
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
434
 
 
435
    float x = -5;
 
436
    float y = 20;
 
437
    setup_pointer_event(fake_event_1, event_time_1, x, y);
 
438
 
 
439
    EXPECT_CALL(mock_sink, handle_input(mt::PointerEventWithDiff(x,y)));
 
440
 
 
441
    dev.start(&mock_sink, &mock_builder);
 
442
    dev.process_event(fake_event_1);
 
443
}
 
444
 
 
445
TEST_F(LibInputDevice, process_event_accumulates_pointer_movement)
 
446
{
 
447
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
448
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
449
 
 
450
    float x1 = 15, x2 = 23;
 
451
    float y1 = 17, y2 = 21;
 
452
 
 
453
    setup_pointer_event(fake_event_1, event_time_1, x1, y1);
 
454
    setup_pointer_event(fake_event_2, event_time_2, x2, y2);
 
455
 
 
456
    EXPECT_CALL(mock_sink, handle_input(mt::PointerEventWithPosition(x1,y1)));
 
457
    EXPECT_CALL(mock_sink, handle_input(mt::PointerEventWithPosition(x1+x2,y1+y2)));
 
458
 
 
459
    dev.start(&mock_sink, &mock_builder);
 
460
    dev.process_event(fake_event_1);
 
461
    dev.process_event(fake_event_2);
 
462
}
 
463
 
 
464
TEST_F(LibInputDevice, process_event_handles_press_and_release)
 
465
{
 
466
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
467
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
468
    float const x = 0;
 
469
    float const y = 0;
 
470
    geom::Point const pos{x,y};
 
471
 
 
472
    setup_button_event(fake_event_1, event_time_1, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
 
473
    setup_button_event(fake_event_2, event_time_2, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED);
 
474
    setup_button_event(fake_event_3, event_time_3, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED);
 
475
    setup_button_event(fake_event_4, event_time_4, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED);
 
476
 
 
477
    InSequence seq;
 
478
    EXPECT_CALL(mock_sink, handle_input(mt::ButtonDownEventWithButton(pos, mir_pointer_button_primary)));
 
479
    EXPECT_CALL(mock_sink, handle_input(mt::ButtonDownEventWithButton(pos, mir_pointer_button_secondary)));
 
480
    EXPECT_CALL(mock_sink, handle_input(mt::ButtonUpEventWithButton(pos, mir_pointer_button_secondary)));
 
481
    EXPECT_CALL(mock_sink, handle_input(mt::ButtonUpEventWithButton(pos, mir_pointer_button_primary)));
 
482
 
 
483
    dev.start(&mock_sink, &mock_builder);
 
484
    dev.process_event(fake_event_1);
 
485
    dev.process_event(fake_event_2);
 
486
    dev.process_event(fake_event_3);
 
487
    dev.process_event(fake_event_4);
 
488
}
 
489
 
 
490
TEST_F(LibInputDevice, process_event_handles_scroll)
 
491
{
 
492
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
493
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
494
 
 
495
    setup_axis_event(fake_event_1, event_time_1, 0.0, 20.0);
 
496
    setup_axis_event(fake_event_2, event_time_2, 5.0, 0.0);
 
497
 
 
498
    InSequence seq;
 
499
    // expect two scroll events..
 
500
    EXPECT_CALL(mock_builder, pointer_event(time_stamp_1, mir_input_event_modifier_none, mir_pointer_action_motion, 0, 0.0f, 0.0f, 0.0f, 20.0f, 0.0f, 0.0f));
 
501
    EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_vscroll, 20.0f)));
 
502
    EXPECT_CALL(mock_builder, pointer_event(time_stamp_2, mir_input_event_modifier_none, mir_pointer_action_motion, 0, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f));
 
503
    EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_hscroll, 5.0f)));
 
504
 
 
505
    dev.start(&mock_sink, &mock_builder);
 
506
    dev.process_event(fake_event_1);
 
507
    dev.process_event(fake_event_2);
 
508
}
 
509
 
 
510
TEST_F(LibInputDevice, process_event_handles_touch_down_events)
 
511
{
 
512
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
513
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
514
 
 
515
    int slot = 0;
 
516
    float major = 6;
 
517
    float minor = 5;
 
518
    float pressure = 0.6f;
 
519
    float x = 100;
 
520
    float y = 7;
 
521
 
 
522
    setup_touch_event(fake_event_1, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, slot, x, y, major, minor, pressure);
 
523
    setup_touch_frame(fake_event_2);
 
524
 
 
525
    InSequence seq;
 
526
    EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));
 
527
    EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,
 
528
                                        pressure, major, minor, major));
 
529
    EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x,y)));
 
530
 
 
531
    dev.start(&mock_sink, &mock_builder);
 
532
    dev.process_event(fake_event_1);
 
533
    dev.process_event(fake_event_2);
 
534
}
 
535
 
 
536
TEST_F(LibInputDevice, process_event_handles_touch_move_events)
 
537
{
 
538
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
539
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
540
 
 
541
    int slot = 0;
 
542
    float major = 6;
 
543
    float minor = 5;
 
544
    float pressure = 0.6f;
 
545
    float x = 100;
 
546
    float y = 7;
 
547
 
 
548
    setup_touch_event(fake_event_1, LIBINPUT_EVENT_TOUCH_MOTION, event_time_1, slot, x, y, major, minor, pressure);
 
549
    setup_touch_frame(fake_event_2);
 
550
 
 
551
    InSequence seq;
 
552
    EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));
 
553
    EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_change, mir_touch_tooltype_finger, x, y,
 
554
                                        pressure, major, minor, major));
 
555
    EXPECT_CALL(mock_sink, handle_input(mt::TouchMovementEvent()));
 
556
 
 
557
    dev.start(&mock_sink, &mock_builder);
 
558
    dev.process_event(fake_event_1);
 
559
    dev.process_event(fake_event_2);
 
560
}
 
561
 
 
562
TEST_F(LibInputDevice, process_event_handles_touch_up_events_without_querying_properties)
 
563
{
 
564
    std::shared_ptr<libinput> lib = mie::make_libinput();
 
565
    mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
 
566
 
 
567
    int slot = 3;
 
568
    float major = 6;
 
569
    float minor = 5;
 
570
    float pressure = 0.6f;
 
571
    float x = 30;
 
572
    float y = 20;
 
573
 
 
574
    setup_touch_event(fake_event_1, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, slot, x, y, major, minor, pressure);
 
575
    setup_touch_frame(fake_event_2);
 
576
    setup_touch_up_event(fake_event_3, event_time_2, slot);
 
577
    setup_touch_frame(fake_event_4);
 
578
 
 
579
    InSequence seq;
 
580
    EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));
 
581
    EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,
 
582
                                        pressure, major, minor, major));
 
583
    EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x,y)));
 
584
 
 
585
    EXPECT_CALL(mock_builder, touch_event(time_stamp_2, mir_input_event_modifier_none));
 
586
    EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_up, mir_touch_tooltype_finger, x, y,
 
587
                                        pressure, major, minor, major));
 
588
    EXPECT_CALL(mock_sink, handle_input(mt::TouchUpEvent(x,y)));
 
589
 
 
590
    dev.start(&mock_sink, &mock_builder);
 
591
    dev.process_event(fake_event_1);
 
592
    dev.process_event(fake_event_2);
 
593
    dev.process_event(fake_event_3);
 
594
    dev.process_event(fake_event_4);
 
595
}