2
* Copyright © 2015 Canonical Ltd.
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.
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.
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/>.
16
* Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
19
#include "fake_input_device_impl.h"
20
#include "stub_input_platform.h"
22
#include "mir/input/input_device.h"
23
#include "mir/input/input_device_info.h"
24
#include "mir/input/input_sink.h"
25
#include "mir/dispatch/action_queue.h"
26
#include "mir/module_deleter.h"
28
#include "boost/throw_exception.hpp"
29
#include "linux/input.h"
31
#include "mir/events/event_builders.h"
35
namespace mi = mir::input;
36
namespace md = mir::dispatch;
37
namespace mtf = mir_test_framework;
41
uint32_t to_modifier(int32_t scan_code)
46
return mir_input_event_modifier_alt_left;
48
return mir_input_event_modifier_alt_right;
50
return mir_input_event_modifier_ctrl_right;
52
return mir_input_event_modifier_ctrl_left;
54
return mir_input_event_modifier_caps_lock;
56
return mir_input_event_modifier_meta_left;
58
return mir_input_event_modifier_meta_right;
60
return mir_input_event_modifier_scroll_lock;
62
return mir_input_event_modifier_num_lock;
64
return mir_input_event_modifier_shift_left;
66
return mir_input_event_modifier_shift_right;
68
return mir_input_event_modifier_none;
72
uint32_t expand_modifier(uint32_t modifiers)
74
if ((modifiers&mir_input_event_modifier_alt_left) ||
75
(modifiers&mir_input_event_modifier_alt_right))
76
modifiers |= mir_input_event_modifier_alt;
78
if ((modifiers&mir_input_event_modifier_ctrl_left) ||
79
(modifiers&mir_input_event_modifier_ctrl_right))
80
modifiers |= mir_input_event_modifier_ctrl;
82
if ((modifiers&mir_input_event_modifier_shift_left) ||
83
(modifiers&mir_input_event_modifier_shift_right))
84
modifiers |= mir_input_event_modifier_shift;
86
if ((modifiers&mir_input_event_modifier_meta_left) ||
87
(modifiers&mir_input_event_modifier_meta_right))
88
modifiers |= mir_input_event_modifier_meta;
95
mtf::FakeInputDeviceImpl::FakeInputDeviceImpl(mi::InputDeviceInfo const& info)
96
: queue{mir::make_module_ptr<md::ActionQueue>()},
97
device{mir::make_module_ptr<InputDevice>(info, queue)}
99
mtf::StubInputPlatform::add(device);
102
void mtf::FakeInputDeviceImpl::emit_event(synthesis::KeyParameters const& key)
104
queue->enqueue([this, key]()
106
device->synthesize_events(key);
110
mtf::FakeInputDeviceImpl::InputDevice::InputDevice(mi::InputDeviceInfo const& info,
111
std::shared_ptr<mir::dispatch::Dispatchable> const& dispatchable)
112
: info(info), queue{dispatchable}
116
void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::KeyParameters const& key_params)
118
int64_t device_id_unknown = 0;
119
xkb_keysym_t key_code = 0;
120
int64_t event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
121
std::chrono::system_clock::now().time_since_epoch()).count();
122
auto input_action = (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down:
123
mir_keyboard_action_up;
125
auto event_modifiers = expand_modifier(modifiers);
126
auto key_event = mir::events::make_event(
127
device_id_unknown, event_time, input_action, key_code, key_params.scancode, event_modifiers);
129
if (key_params.action == synthesis::EventAction::Down)
130
modifiers |= to_modifier(key_params.scancode);
132
modifiers &= ~to_modifier(key_params.scancode);
135
BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));
136
sink->handle_input(*key_event);
139
std::shared_ptr<md::Dispatchable> mtf::FakeInputDeviceImpl::InputDevice::dispatchable()
144
void mtf::FakeInputDeviceImpl::InputDevice::start(mi::InputSink* destination)
149
void mtf::FakeInputDeviceImpl::InputDevice::stop()