Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / events / ozone / evdev / event_factory_evdev.cc
blobfe2150158d2d816107c222ef6988ced5b29fa0e7
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"
7 #include "base/bind.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"
24 namespace ui {
26 namespace {
28 // Thread safe dispatcher proxy for EventFactoryEvdev.
30 // This is used on the device I/O thread for dispatching to UI.
31 class ProxyDeviceEventDispatcher : public DeviceEventDispatcherEvdev {
32 public:
33 ProxyDeviceEventDispatcher(
34 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner,
35 base::WeakPtr<EventFactoryEvdev> event_factory_evdev)
36 : ui_thread_runner_(ui_thread_runner),
37 event_factory_evdev_(event_factory_evdev) {}
38 ~ProxyDeviceEventDispatcher() override {}
40 // DeviceEventDispatcher:
41 void DispatchKeyEvent(const KeyEventParams& params) override {
42 ui_thread_runner_->PostTask(FROM_HERE,
43 base::Bind(&EventFactoryEvdev::DispatchKeyEvent,
44 event_factory_evdev_, params));
47 void DispatchMouseMoveEvent(const MouseMoveEventParams& params) override {
48 ui_thread_runner_->PostTask(
49 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent,
50 event_factory_evdev_, params));
53 void DispatchMouseButtonEvent(const MouseButtonEventParams& params) override {
54 ui_thread_runner_->PostTask(
55 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseButtonEvent,
56 event_factory_evdev_, params));
59 void DispatchMouseWheelEvent(const MouseWheelEventParams& params) override {
60 ui_thread_runner_->PostTask(
61 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseWheelEvent,
62 event_factory_evdev_, params));
65 void DispatchScrollEvent(const ScrollEventParams& params) override {
66 ui_thread_runner_->PostTask(
67 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchScrollEvent,
68 event_factory_evdev_, params));
71 void DispatchTouchEvent(const TouchEventParams& params) override {
72 ui_thread_runner_->PostTask(
73 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchTouchEvent,
74 event_factory_evdev_, params));
77 void DispatchKeyboardDevicesUpdated(
78 const std::vector<KeyboardDevice>& devices) override {
79 ui_thread_runner_->PostTask(
80 FROM_HERE,
81 base::Bind(&EventFactoryEvdev::DispatchKeyboardDevicesUpdated,
82 event_factory_evdev_, devices));
84 void DispatchTouchscreenDevicesUpdated(
85 const std::vector<TouchscreenDevice>& devices) override {
86 ui_thread_runner_->PostTask(
87 FROM_HERE,
88 base::Bind(&EventFactoryEvdev::DispatchTouchscreenDevicesUpdated,
89 event_factory_evdev_, devices));
91 void DispatchMouseDevicesUpdated(
92 const std::vector<InputDevice>& devices) override {
93 ui_thread_runner_->PostTask(
94 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseDevicesUpdated,
95 event_factory_evdev_, devices));
97 void DispatchTouchpadDevicesUpdated(
98 const std::vector<InputDevice>& devices) override {
99 ui_thread_runner_->PostTask(
100 FROM_HERE,
101 base::Bind(&EventFactoryEvdev::DispatchTouchpadDevicesUpdated,
102 event_factory_evdev_, devices));
105 private:
106 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner_;
107 base::WeakPtr<EventFactoryEvdev> event_factory_evdev_;
110 } // namespace
112 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor,
113 DeviceManager* device_manager,
114 KeyboardLayoutEngine* keyboard_layout)
115 : last_device_id_(0),
116 device_manager_(device_manager),
117 keyboard_(&modifiers_,
118 keyboard_layout,
119 base::Bind(&EventFactoryEvdev::DispatchUiEvent,
120 base::Unretained(this))),
121 cursor_(cursor),
122 input_controller_(&keyboard_, &button_map_),
123 initialized_(false),
124 weak_ptr_factory_(this) {
125 DCHECK(device_manager_);
128 EventFactoryEvdev::~EventFactoryEvdev() {
131 void EventFactoryEvdev::Init() {
132 DCHECK(!initialized_);
134 StartThread();
136 initialized_ = true;
139 scoped_ptr<SystemInputInjector> EventFactoryEvdev::CreateSystemInputInjector() {
140 // Use forwarding dispatcher for the injector rather than dispatching
141 // directly. We cannot assume it is safe to (re-)enter ui::Event dispatch
142 // synchronously from the injection point.
143 scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher(
144 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
145 weak_ptr_factory_.GetWeakPtr()));
146 return make_scoped_ptr(
147 new InputInjectorEvdev(proxy_dispatcher.Pass(), cursor_));
150 void EventFactoryEvdev::DispatchKeyEvent(const KeyEventParams& params) {
151 keyboard_.OnKeyChange(params.code, params.down, params.timestamp);
154 void EventFactoryEvdev::DispatchMouseMoveEvent(
155 const MouseMoveEventParams& params) {
156 MouseEvent event(ui::ET_MOUSE_MOVED, params.location, params.location,
157 params.timestamp, modifiers_.GetModifierFlags(),
158 /* changed_button_flags */ 0);
159 event.set_source_device_id(params.device_id);
160 DispatchUiEvent(&event);
163 void EventFactoryEvdev::DispatchMouseButtonEvent(
164 const MouseButtonEventParams& params) {
165 // Mouse buttons can be remapped, touchpad taps & clicks cannot.
166 unsigned int button = params.button;
167 if (params.allow_remap)
168 button = button_map_.GetMappedButton(button);
170 int modifier = EVDEV_MODIFIER_NONE;
171 switch (button) {
172 case BTN_LEFT:
173 modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
174 break;
175 case BTN_RIGHT:
176 modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
177 break;
178 case BTN_MIDDLE:
179 modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
180 break;
181 case BTN_BACK:
182 modifier = EVDEV_MODIFIER_BACK_MOUSE_BUTTON;
183 break;
184 case BTN_FORWARD:
185 modifier = EVDEV_MODIFIER_FORWARD_MOUSE_BUTTON;
186 break;
187 default:
188 return;
191 int flag = modifiers_.GetEventFlagFromModifier(modifier);
192 modifiers_.UpdateModifier(modifier, params.down);
194 MouseEvent event(params.down ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED,
195 params.location, params.location, params.timestamp,
196 modifiers_.GetModifierFlags() | flag,
197 /* changed_button_flags */ flag);
198 event.set_source_device_id(params.device_id);
199 DispatchUiEvent(&event);
202 void EventFactoryEvdev::DispatchMouseWheelEvent(
203 const MouseWheelEventParams& params) {
204 MouseWheelEvent event(params.delta, params.location, params.location,
205 params.timestamp, modifiers_.GetModifierFlags(),
206 0 /* changed_button_flags */);
207 event.set_source_device_id(params.device_id);
208 DispatchUiEvent(&event);
211 void EventFactoryEvdev::DispatchScrollEvent(const ScrollEventParams& params) {
212 ScrollEvent event(params.type, params.location, params.timestamp,
213 modifiers_.GetModifierFlags(), params.delta.x(),
214 params.delta.y(), params.ordinal_delta.x(),
215 params.ordinal_delta.y(), params.finger_count);
216 event.set_source_device_id(params.device_id);
217 DispatchUiEvent(&event);
220 void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams& params) {
221 float x = params.location.x();
222 float y = params.location.y();
223 double radius_x = params.radii.x();
224 double radius_y = params.radii.y();
226 // Transform the event to align touches to the image based on display mode.
227 DeviceDataManager::GetInstance()->ApplyTouchTransformer(params.device_id, &x,
228 &y);
229 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
230 &radius_x);
231 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
232 &radius_y);
234 TouchEvent touch_event(params.type, gfx::PointF(x, y),
235 modifiers_.GetModifierFlags(), params.touch_id,
236 params.timestamp, radius_x, radius_y,
237 /* angle */ 0.f, params.pressure);
238 touch_event.set_source_device_id(params.device_id);
239 DispatchUiEvent(&touch_event);
242 void EventFactoryEvdev::DispatchUiEvent(Event* event) {
243 // DispatchEvent takes PlatformEvent which is void*. This function
244 // wraps it with the real type.
245 DispatchEvent(event);
248 void EventFactoryEvdev::DispatchKeyboardDevicesUpdated(
249 const std::vector<KeyboardDevice>& devices) {
250 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
251 observer->OnKeyboardDevicesUpdated(devices);
254 void EventFactoryEvdev::DispatchTouchscreenDevicesUpdated(
255 const std::vector<TouchscreenDevice>& devices) {
256 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
257 observer->OnTouchscreenDevicesUpdated(devices);
260 void EventFactoryEvdev::DispatchMouseDevicesUpdated(
261 const std::vector<InputDevice>& devices) {
262 // There's no list of mice in DeviceDataManager.
263 input_controller_.set_has_mouse(devices.size() != 0);
264 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
265 observer->OnMouseDevicesUpdated(devices);
268 void EventFactoryEvdev::DispatchTouchpadDevicesUpdated(
269 const std::vector<InputDevice>& devices) {
270 // There's no list of touchpads in DeviceDataManager.
271 input_controller_.set_has_touchpad(devices.size() != 0);
272 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
273 observer->OnTouchpadDevicesUpdated(devices);
277 void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent& event) {
278 if (event.device_type() != DeviceEvent::INPUT)
279 return;
281 switch (event.action_type()) {
282 case DeviceEvent::ADD:
283 case DeviceEvent::CHANGE: {
284 TRACE_EVENT1("ozone", "OnDeviceAdded", "path", event.path().value());
285 input_device_factory_proxy_->AddInputDevice(NextDeviceId(), event.path());
286 break;
288 case DeviceEvent::REMOVE: {
289 TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", event.path().value());
290 input_device_factory_proxy_->RemoveInputDevice(event.path());
291 break;
296 void EventFactoryEvdev::OnDispatcherListChanged() {
297 if (!initialized_)
298 Init();
301 void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget,
302 const gfx::PointF& location) {
303 if (!cursor_)
304 return;
306 cursor_->MoveCursorTo(widget, location);
308 base::ThreadTaskRunnerHandle::Get()->PostTask(
309 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent,
310 weak_ptr_factory_.GetWeakPtr(),
311 MouseMoveEventParams(-1 /* device_id */,
312 cursor_->GetLocation(),
313 EventTimeForNow())));
316 int EventFactoryEvdev::NextDeviceId() {
317 return ++last_device_id_;
320 void EventFactoryEvdev::StartThread() {
321 // Set up device factory.
322 scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher(
323 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
324 weak_ptr_factory_.GetWeakPtr()));
325 thread_.Start(proxy_dispatcher.Pass(), cursor_,
326 base::Bind(&EventFactoryEvdev::OnThreadStarted,
327 weak_ptr_factory_.GetWeakPtr()));
330 void EventFactoryEvdev::OnThreadStarted(
331 scoped_ptr<InputDeviceFactoryEvdevProxy> input_device_factory) {
332 input_device_factory_proxy_ = input_device_factory.Pass();
334 // Hook up device configuration.
335 input_controller_.SetInputDeviceFactory(input_device_factory_proxy_.get());
337 // Scan & monitor devices.
338 device_manager_->AddObserver(this);
339 device_manager_->ScanDevices(this);
342 } // namespace ui