1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/events/ozone/evdev/event_factory_evdev.h"
8 #include "base/task_runner.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/threading/worker_pool.h"
11 #include "base/time/time.h"
12 #include "base/trace_event/trace_event.h"
13 #include "ui/events/devices/device_data_manager.h"
14 #include "ui/events/devices/input_device.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/events/ozone/device/device_event.h"
17 #include "ui/events/ozone/device/device_manager.h"
18 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
19 #include "ui/events/ozone/evdev/input_controller_evdev.h"
20 #include "ui/events/ozone/evdev/input_device_factory_evdev.h"
21 #include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
22 #include "ui/events/ozone/evdev/input_injector_evdev.h"
23 #include "ui/events/ozone/evdev/touch_evdev_types.h"
29 // Thread safe dispatcher proxy for EventFactoryEvdev.
31 // This is used on the device I/O thread for dispatching to UI.
32 class ProxyDeviceEventDispatcher
: public DeviceEventDispatcherEvdev
{
34 ProxyDeviceEventDispatcher(
35 scoped_refptr
<base::SingleThreadTaskRunner
> ui_thread_runner
,
36 base::WeakPtr
<EventFactoryEvdev
> event_factory_evdev
)
37 : ui_thread_runner_(ui_thread_runner
),
38 event_factory_evdev_(event_factory_evdev
) {}
39 ~ProxyDeviceEventDispatcher() override
{}
41 // DeviceEventDispatcher:
42 void DispatchKeyEvent(const KeyEventParams
& params
) override
{
43 ui_thread_runner_
->PostTask(FROM_HERE
,
44 base::Bind(&EventFactoryEvdev::DispatchKeyEvent
,
45 event_factory_evdev_
, params
));
48 void DispatchMouseMoveEvent(const MouseMoveEventParams
& params
) override
{
49 ui_thread_runner_
->PostTask(
50 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent
,
51 event_factory_evdev_
, params
));
54 void DispatchMouseButtonEvent(const MouseButtonEventParams
& params
) override
{
55 ui_thread_runner_
->PostTask(
56 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseButtonEvent
,
57 event_factory_evdev_
, params
));
60 void DispatchMouseWheelEvent(const MouseWheelEventParams
& params
) override
{
61 ui_thread_runner_
->PostTask(
62 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseWheelEvent
,
63 event_factory_evdev_
, params
));
66 void DispatchScrollEvent(const ScrollEventParams
& params
) override
{
67 ui_thread_runner_
->PostTask(
68 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchScrollEvent
,
69 event_factory_evdev_
, params
));
72 void DispatchTouchEvent(const TouchEventParams
& params
) override
{
73 ui_thread_runner_
->PostTask(
74 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchTouchEvent
,
75 event_factory_evdev_
, params
));
78 void DispatchKeyboardDevicesUpdated(
79 const std::vector
<KeyboardDevice
>& devices
) override
{
80 ui_thread_runner_
->PostTask(
82 base::Bind(&EventFactoryEvdev::DispatchKeyboardDevicesUpdated
,
83 event_factory_evdev_
, devices
));
85 void DispatchTouchscreenDevicesUpdated(
86 const std::vector
<TouchscreenDevice
>& devices
) override
{
87 ui_thread_runner_
->PostTask(
89 base::Bind(&EventFactoryEvdev::DispatchTouchscreenDevicesUpdated
,
90 event_factory_evdev_
, devices
));
92 void DispatchMouseDevicesUpdated(
93 const std::vector
<InputDevice
>& devices
) override
{
94 ui_thread_runner_
->PostTask(
95 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseDevicesUpdated
,
96 event_factory_evdev_
, devices
));
98 void DispatchTouchpadDevicesUpdated(
99 const std::vector
<InputDevice
>& devices
) override
{
100 ui_thread_runner_
->PostTask(
102 base::Bind(&EventFactoryEvdev::DispatchTouchpadDevicesUpdated
,
103 event_factory_evdev_
, devices
));
105 void DispatchDeviceListsComplete() override
{
106 ui_thread_runner_
->PostTask(
107 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchDeviceListsComplete
,
108 event_factory_evdev_
));
112 scoped_refptr
<base::SingleThreadTaskRunner
> ui_thread_runner_
;
113 base::WeakPtr
<EventFactoryEvdev
> event_factory_evdev_
;
118 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev
* cursor
,
119 DeviceManager
* device_manager
,
120 KeyboardLayoutEngine
* keyboard_layout
)
121 : device_manager_(device_manager
),
122 keyboard_(&modifiers_
,
124 base::Bind(&EventFactoryEvdev::DispatchUiEvent
,
125 base::Unretained(this))),
127 input_controller_(&keyboard_
, &button_map_
),
128 touch_id_generator_(0),
129 weak_ptr_factory_(this) {
130 DCHECK(device_manager_
);
133 EventFactoryEvdev::~EventFactoryEvdev() {
136 void EventFactoryEvdev::Init() {
137 DCHECK(!initialized_
);
144 scoped_ptr
<SystemInputInjector
> EventFactoryEvdev::CreateSystemInputInjector() {
145 // Use forwarding dispatcher for the injector rather than dispatching
146 // directly. We cannot assume it is safe to (re-)enter ui::Event dispatch
147 // synchronously from the injection point.
148 scoped_ptr
<DeviceEventDispatcherEvdev
> proxy_dispatcher(
149 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
150 weak_ptr_factory_
.GetWeakPtr()));
151 return make_scoped_ptr(
152 new InputInjectorEvdev(proxy_dispatcher
.Pass(), cursor_
));
155 void EventFactoryEvdev::DispatchKeyEvent(const KeyEventParams
& params
) {
156 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchKeyEvent", "device",
158 keyboard_
.OnKeyChange(params
.code
, params
.down
, params
.suppress_auto_repeat
,
159 params
.timestamp
, params
.device_id
);
162 void EventFactoryEvdev::DispatchMouseMoveEvent(
163 const MouseMoveEventParams
& params
) {
164 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseMoveEvent", "device",
166 MouseEvent
event(ui::ET_MOUSE_MOVED
, params
.location
, params
.location
,
167 params
.timestamp
, modifiers_
.GetModifierFlags(),
168 /* changed_button_flags */ 0);
169 event
.set_source_device_id(params
.device_id
);
170 event
.set_pointer_details(params
.pointer_details
);
171 DispatchUiEvent(&event
);
174 void EventFactoryEvdev::DispatchMouseButtonEvent(
175 const MouseButtonEventParams
& params
) {
176 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseButtonEvent", "device",
179 // Mouse buttons can be remapped, touchpad taps & clicks cannot.
180 unsigned int button
= params
.button
;
181 if (params
.allow_remap
)
182 button
= button_map_
.GetMappedButton(button
);
184 int modifier
= EVDEV_MODIFIER_NONE
;
187 modifier
= EVDEV_MODIFIER_LEFT_MOUSE_BUTTON
;
190 modifier
= EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON
;
193 modifier
= EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON
;
196 modifier
= EVDEV_MODIFIER_BACK_MOUSE_BUTTON
;
199 modifier
= EVDEV_MODIFIER_FORWARD_MOUSE_BUTTON
;
205 int flag
= modifiers_
.GetEventFlagFromModifier(modifier
);
206 bool was_down
= modifiers_
.GetModifierFlags() & flag
;
207 modifiers_
.UpdateModifier(modifier
, params
.down
);
208 bool down
= modifiers_
.GetModifierFlags() & flag
;
210 // Suppress nested clicks. EventModifiersEvdev counts presses, we only
211 // dispatch an event on 0-1 (first press) and 1-0 (last release) transitions.
212 if (down
== was_down
)
215 MouseEvent
event(params
.down
? ui::ET_MOUSE_PRESSED
: ui::ET_MOUSE_RELEASED
,
216 params
.location
, params
.location
, params
.timestamp
,
217 modifiers_
.GetModifierFlags() | flag
,
218 /* changed_button_flags */ flag
);
219 event
.set_source_device_id(params
.device_id
);
220 event
.set_pointer_details(params
.pointer_details
);
221 DispatchUiEvent(&event
);
224 void EventFactoryEvdev::DispatchMouseWheelEvent(
225 const MouseWheelEventParams
& params
) {
226 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseWheelEvent", "device",
228 MouseWheelEvent
event(params
.delta
, params
.location
, params
.location
,
229 params
.timestamp
, modifiers_
.GetModifierFlags(),
230 0 /* changed_button_flags */);
231 event
.set_source_device_id(params
.device_id
);
232 DispatchUiEvent(&event
);
235 void EventFactoryEvdev::DispatchScrollEvent(const ScrollEventParams
& params
) {
236 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchScrollEvent", "device",
238 ScrollEvent
event(params
.type
, params
.location
, params
.timestamp
,
239 modifiers_
.GetModifierFlags(), params
.delta
.x(),
240 params
.delta
.y(), params
.ordinal_delta
.x(),
241 params
.ordinal_delta
.y(), params
.finger_count
);
242 event
.set_source_device_id(params
.device_id
);
243 DispatchUiEvent(&event
);
246 void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams
& params
) {
247 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchTouchEvent", "device",
250 float x
= params
.location
.x();
251 float y
= params
.location
.y();
252 double radius_x
= params
.radii
.x();
253 double radius_y
= params
.radii
.y();
255 // Transform the event to align touches to the image based on display mode.
256 DeviceDataManager::GetInstance()->ApplyTouchTransformer(params
.device_id
, &x
,
258 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params
.device_id
,
260 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params
.device_id
,
263 // params.slot is guaranteed to be < kNumTouchEvdevSlots.
264 int touch_id
= touch_id_generator_
.GetGeneratedID(
265 params
.device_id
* kNumTouchEvdevSlots
+ params
.slot
);
266 TouchEvent
touch_event(params
.type
, gfx::PointF(x
, y
),
267 modifiers_
.GetModifierFlags(), touch_id
,
268 params
.timestamp
, radius_x
, radius_y
,
269 /* angle */ 0.f
, params
.pressure
);
270 touch_event
.set_source_device_id(params
.device_id
);
271 DispatchUiEvent(&touch_event
);
273 if (params
.type
== ET_TOUCH_RELEASED
|| params
.type
== ET_TOUCH_CANCELLED
) {
274 touch_id_generator_
.ReleaseGeneratedID(touch_event
.touch_id());
278 void EventFactoryEvdev::DispatchUiEvent(Event
* event
) {
279 // DispatchEvent takes PlatformEvent which is void*. This function
280 // wraps it with the real type.
281 DispatchEvent(event
);
284 void EventFactoryEvdev::DispatchKeyboardDevicesUpdated(
285 const std::vector
<KeyboardDevice
>& devices
) {
286 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchKeyboardDevicesUpdated");
287 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
288 observer
->OnKeyboardDevicesUpdated(devices
);
291 void EventFactoryEvdev::DispatchTouchscreenDevicesUpdated(
292 const std::vector
<TouchscreenDevice
>& devices
) {
293 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchscreenDevicesUpdated");
294 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
295 observer
->OnTouchscreenDevicesUpdated(devices
);
298 void EventFactoryEvdev::DispatchMouseDevicesUpdated(
299 const std::vector
<InputDevice
>& devices
) {
300 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchMouseDevicesUpdated");
302 // There's no list of mice in DeviceDataManager.
303 input_controller_
.set_has_mouse(devices
.size() != 0);
304 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
305 observer
->OnMouseDevicesUpdated(devices
);
308 void EventFactoryEvdev::DispatchTouchpadDevicesUpdated(
309 const std::vector
<InputDevice
>& devices
) {
310 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchpadDevicesUpdated");
312 // There's no list of touchpads in DeviceDataManager.
313 input_controller_
.set_has_touchpad(devices
.size() != 0);
314 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
315 observer
->OnTouchpadDevicesUpdated(devices
);
318 void EventFactoryEvdev::DispatchDeviceListsComplete() {
319 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchDeviceListsComplete");
320 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
321 observer
->OnDeviceListsComplete();
324 void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent
& event
) {
325 if (event
.device_type() != DeviceEvent::INPUT
)
328 switch (event
.action_type()) {
329 case DeviceEvent::ADD
:
330 case DeviceEvent::CHANGE
: {
331 TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceAdded", "path",
332 event
.path().value());
333 input_device_factory_proxy_
->AddInputDevice(NextDeviceId(), event
.path());
336 case DeviceEvent::REMOVE
: {
337 TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceRemoved", "path",
338 event
.path().value());
339 input_device_factory_proxy_
->RemoveInputDevice(event
.path());
345 void EventFactoryEvdev::OnDispatcherListChanged() {
350 void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget
,
351 const gfx::PointF
& location
) {
355 cursor_
->MoveCursorTo(widget
, location
);
357 base::ThreadTaskRunnerHandle::Get()->PostTask(
359 base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent
,
360 weak_ptr_factory_
.GetWeakPtr(),
361 MouseMoveEventParams(
362 -1 /* device_id */, cursor_
->GetLocation(),
363 PointerDetails(EventPointerType::POINTER_TYPE_MOUSE
),
364 EventTimeForNow())));
367 int EventFactoryEvdev::NextDeviceId() {
368 return ++last_device_id_
;
371 void EventFactoryEvdev::StartThread() {
372 // Set up device factory.
373 scoped_ptr
<DeviceEventDispatcherEvdev
> proxy_dispatcher(
374 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
375 weak_ptr_factory_
.GetWeakPtr()));
376 thread_
.Start(proxy_dispatcher
.Pass(), cursor_
,
377 base::Bind(&EventFactoryEvdev::OnThreadStarted
,
378 weak_ptr_factory_
.GetWeakPtr()));
381 void EventFactoryEvdev::OnThreadStarted(
382 scoped_ptr
<InputDeviceFactoryEvdevProxy
> input_device_factory
) {
383 TRACE_EVENT0("evdev", "EventFactoryEvdev::OnThreadStarted");
384 input_device_factory_proxy_
= input_device_factory
.Pass();
386 // Hook up device configuration.
387 input_controller_
.SetInputDeviceFactory(input_device_factory_proxy_
.get());
389 // Scan & monitor devices.
390 device_manager_
->AddObserver(this);
391 device_manager_
->ScanDevices(this);
393 // Notify device thread that initial scan is done.
394 input_device_factory_proxy_
->OnStartupScanComplete();