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/ozone/device/device_event.h"
16 #include "ui/events/ozone/device/device_manager.h"
17 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
18 #include "ui/events/ozone/evdev/input_controller_evdev.h"
19 #include "ui/events/ozone/evdev/input_device_factory_evdev.h"
20 #include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
21 #include "ui/events/ozone/evdev/input_injector_evdev.h"
27 // Thread safe dispatcher proxy for EventFactoryEvdev.
29 // This is used on the device I/O thread for dispatching to UI.
30 class ProxyDeviceEventDispatcher
: public DeviceEventDispatcherEvdev
{
32 ProxyDeviceEventDispatcher(
33 scoped_refptr
<base::SingleThreadTaskRunner
> ui_thread_runner
,
34 base::WeakPtr
<EventFactoryEvdev
> event_factory_evdev
)
35 : ui_thread_runner_(ui_thread_runner
),
36 event_factory_evdev_(event_factory_evdev
) {}
37 ~ProxyDeviceEventDispatcher() override
{}
39 // DeviceEventDispatcher:
40 void DispatchKeyEvent(const KeyEventParams
& params
) override
{
41 ui_thread_runner_
->PostTask(FROM_HERE
,
42 base::Bind(&EventFactoryEvdev::DispatchKeyEvent
,
43 event_factory_evdev_
, params
));
46 void DispatchMouseMoveEvent(const MouseMoveEventParams
& params
) override
{
47 ui_thread_runner_
->PostTask(
48 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent
,
49 event_factory_evdev_
, params
));
52 void DispatchMouseButtonEvent(const MouseButtonEventParams
& params
) override
{
53 ui_thread_runner_
->PostTask(
54 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseButtonEvent
,
55 event_factory_evdev_
, params
));
58 void DispatchMouseWheelEvent(const MouseWheelEventParams
& params
) override
{
59 ui_thread_runner_
->PostTask(
60 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseWheelEvent
,
61 event_factory_evdev_
, params
));
64 void DispatchScrollEvent(const ScrollEventParams
& params
) override
{
65 ui_thread_runner_
->PostTask(
66 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchScrollEvent
,
67 event_factory_evdev_
, params
));
70 void DispatchTouchEvent(const TouchEventParams
& params
) override
{
71 ui_thread_runner_
->PostTask(
72 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchTouchEvent
,
73 event_factory_evdev_
, params
));
76 void DispatchKeyboardDevicesUpdated(
77 const std::vector
<KeyboardDevice
>& devices
) override
{
78 ui_thread_runner_
->PostTask(
80 base::Bind(&EventFactoryEvdev::DispatchKeyboardDevicesUpdated
,
81 event_factory_evdev_
, devices
));
83 void DispatchTouchscreenDevicesUpdated(
84 const std::vector
<TouchscreenDevice
>& devices
) override
{
85 ui_thread_runner_
->PostTask(
87 base::Bind(&EventFactoryEvdev::DispatchTouchscreenDevicesUpdated
,
88 event_factory_evdev_
, devices
));
90 void DispatchMouseDevicesUpdated(
91 const std::vector
<InputDevice
>& devices
) override
{
92 ui_thread_runner_
->PostTask(
93 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseDevicesUpdated
,
94 event_factory_evdev_
, devices
));
96 void DispatchTouchpadDevicesUpdated(
97 const std::vector
<InputDevice
>& devices
) override
{
98 ui_thread_runner_
->PostTask(
100 base::Bind(&EventFactoryEvdev::DispatchTouchpadDevicesUpdated
,
101 event_factory_evdev_
, devices
));
105 scoped_refptr
<base::SingleThreadTaskRunner
> ui_thread_runner_
;
106 base::WeakPtr
<EventFactoryEvdev
> event_factory_evdev_
;
111 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev
* cursor
,
112 DeviceManager
* device_manager
,
113 KeyboardLayoutEngine
* keyboard_layout
)
114 : last_device_id_(0),
115 device_manager_(device_manager
),
116 keyboard_(&modifiers_
,
118 base::Bind(&EventFactoryEvdev::DispatchUiEvent
,
119 base::Unretained(this))),
121 input_controller_(&keyboard_
, &button_map_
),
123 weak_ptr_factory_(this) {
124 DCHECK(device_manager_
);
127 EventFactoryEvdev::~EventFactoryEvdev() {
130 void EventFactoryEvdev::Init() {
131 DCHECK(!initialized_
);
138 scoped_ptr
<SystemInputInjector
> EventFactoryEvdev::CreateSystemInputInjector() {
139 // Use forwarding dispatcher for the injector rather than dispatching
140 // directly. We cannot assume it is safe to (re-)enter ui::Event dispatch
141 // synchronously from the injection point.
142 scoped_ptr
<DeviceEventDispatcherEvdev
> proxy_dispatcher(
143 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
144 weak_ptr_factory_
.GetWeakPtr()));
145 return make_scoped_ptr(
146 new InputInjectorEvdev(proxy_dispatcher
.Pass(), cursor_
));
149 void EventFactoryEvdev::DispatchKeyEvent(const KeyEventParams
& params
) {
150 keyboard_
.OnKeyChange(params
.code
, params
.down
);
153 void EventFactoryEvdev::DispatchMouseMoveEvent(
154 const MouseMoveEventParams
& params
) {
155 MouseEvent
event(ui::ET_MOUSE_MOVED
, params
.location
, params
.location
,
156 modifiers_
.GetModifierFlags(),
157 /* changed_button_flags */ 0);
158 event
.set_source_device_id(params
.device_id
);
159 DispatchUiEvent(&event
);
162 void EventFactoryEvdev::DispatchMouseButtonEvent(
163 const MouseButtonEventParams
& params
) {
164 // Mouse buttons can be remapped, touchpad taps & clicks cannot.
165 unsigned int button
= params
.button
;
166 if (params
.allow_remap
)
167 button
= button_map_
.GetMappedButton(button
);
169 int modifier
= EVDEV_MODIFIER_NONE
;
172 modifier
= EVDEV_MODIFIER_LEFT_MOUSE_BUTTON
;
175 modifier
= EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON
;
178 modifier
= EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON
;
184 int flag
= modifiers_
.GetEventFlagFromModifier(modifier
);
185 modifiers_
.UpdateModifier(modifier
, params
.down
);
187 MouseEvent
event(params
.down
? ui::ET_MOUSE_PRESSED
: ui::ET_MOUSE_RELEASED
,
188 params
.location
, params
.location
,
189 modifiers_
.GetModifierFlags() | flag
,
190 /* changed_button_flags */ flag
);
191 event
.set_source_device_id(params
.device_id
);
192 DispatchUiEvent(&event
);
195 void EventFactoryEvdev::DispatchMouseWheelEvent(
196 const MouseWheelEventParams
& params
) {
197 MouseWheelEvent
event(params
.delta
, params
.location
, params
.location
,
198 modifiers_
.GetModifierFlags(),
199 0 /* changed_button_flags */);
200 event
.set_source_device_id(params
.device_id
);
201 DispatchUiEvent(&event
);
204 void EventFactoryEvdev::DispatchScrollEvent(const ScrollEventParams
& params
) {
205 ScrollEvent
event(params
.type
, params
.location
, params
.timestamp
,
206 modifiers_
.GetModifierFlags(), params
.delta
.x(),
207 params
.delta
.y(), params
.ordinal_delta
.x(),
208 params
.ordinal_delta
.y(), params
.finger_count
);
209 event
.set_source_device_id(params
.device_id
);
210 DispatchUiEvent(&event
);
213 void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams
& params
) {
214 float x
= params
.location
.x();
215 float y
= params
.location
.y();
216 double radius_x
= params
.radii
.x();
217 double radius_y
= params
.radii
.y();
219 // Transform the event to align touches to the image based on display mode.
220 DeviceDataManager::GetInstance()->ApplyTouchTransformer(params
.device_id
, &x
,
222 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params
.device_id
,
224 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params
.device_id
,
227 TouchEvent
touch_event(params
.type
, gfx::PointF(x
, y
),
228 modifiers_
.GetModifierFlags(), params
.touch_id
,
229 params
.timestamp
, radius_x
, radius_y
,
230 /* angle */ 0.f
, params
.pressure
);
231 touch_event
.set_source_device_id(params
.device_id
);
232 DispatchUiEvent(&touch_event
);
235 void EventFactoryEvdev::DispatchUiEvent(Event
* event
) {
236 // DispatchEvent takes PlatformEvent which is void*. This function
237 // wraps it with the real type.
238 DispatchEvent(event
);
241 void EventFactoryEvdev::DispatchKeyboardDevicesUpdated(
242 const std::vector
<KeyboardDevice
>& devices
) {
243 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
244 observer
->OnKeyboardDevicesUpdated(devices
);
247 void EventFactoryEvdev::DispatchTouchscreenDevicesUpdated(
248 const std::vector
<TouchscreenDevice
>& devices
) {
249 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
250 observer
->OnTouchscreenDevicesUpdated(devices
);
253 void EventFactoryEvdev::DispatchMouseDevicesUpdated(
254 const std::vector
<InputDevice
>& devices
) {
255 // There's no list of mice in DeviceDataManager.
256 input_controller_
.set_has_mouse(devices
.size() != 0);
257 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
258 observer
->OnMouseDevicesUpdated(devices
);
261 void EventFactoryEvdev::DispatchTouchpadDevicesUpdated(
262 const std::vector
<InputDevice
>& devices
) {
263 // There's no list of touchpads in DeviceDataManager.
264 input_controller_
.set_has_touchpad(devices
.size() != 0);
265 DeviceHotplugEventObserver
* observer
= DeviceDataManager::GetInstance();
266 observer
->OnTouchpadDevicesUpdated(devices
);
270 void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent
& event
) {
271 if (event
.device_type() != DeviceEvent::INPUT
)
274 switch (event
.action_type()) {
275 case DeviceEvent::ADD
:
276 case DeviceEvent::CHANGE
: {
277 TRACE_EVENT1("ozone", "OnDeviceAdded", "path", event
.path().value());
278 input_device_factory_proxy_
->AddInputDevice(NextDeviceId(), event
.path());
281 case DeviceEvent::REMOVE
: {
282 TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", event
.path().value());
283 input_device_factory_proxy_
->RemoveInputDevice(event
.path());
289 void EventFactoryEvdev::OnDispatcherListChanged() {
294 void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget
,
295 const gfx::PointF
& location
) {
299 cursor_
->MoveCursorTo(widget
, location
);
301 base::ThreadTaskRunnerHandle::Get()->PostTask(
302 FROM_HERE
, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent
,
303 weak_ptr_factory_
.GetWeakPtr(),
304 MouseMoveEventParams(-1 /* device_id */,
305 cursor_
->GetLocation())));
308 int EventFactoryEvdev::NextDeviceId() {
309 return ++last_device_id_
;
312 void EventFactoryEvdev::StartThread() {
313 // Set up device factory.
314 scoped_ptr
<DeviceEventDispatcherEvdev
> proxy_dispatcher(
315 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
316 weak_ptr_factory_
.GetWeakPtr()));
317 thread_
.Start(proxy_dispatcher
.Pass(), cursor_
,
318 base::Bind(&EventFactoryEvdev::OnThreadStarted
,
319 weak_ptr_factory_
.GetWeakPtr()));
322 void EventFactoryEvdev::OnThreadStarted(
323 scoped_ptr
<InputDeviceFactoryEvdevProxy
> input_device_factory
) {
324 input_device_factory_proxy_
= input_device_factory
.Pass();
326 // TODO(spang): This settings interface is really broken. crbug.com/450899
327 input_controller_
.SetInputDeviceFactory(input_device_factory_proxy_
.get());
329 // Scan & monitor devices.
330 device_manager_
->AddObserver(this);
331 device_manager_
->ScanDevices(this);