Landing Recent QUIC Changes.
[chromium-blink-merge.git] / ui / events / ozone / evdev / event_factory_evdev.cc
blob11ede97501eca3850152b579567df1bd6baf73b4
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/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"
23 namespace ui {
25 namespace {
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 {
31 public:
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(
79 FROM_HERE,
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(
86 FROM_HERE,
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(
99 FROM_HERE,
100 base::Bind(&EventFactoryEvdev::DispatchTouchpadDevicesUpdated,
101 event_factory_evdev_, devices));
104 private:
105 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner_;
106 base::WeakPtr<EventFactoryEvdev> event_factory_evdev_;
109 } // namespace
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_,
117 keyboard_layout,
118 base::Bind(&EventFactoryEvdev::DispatchUiEvent,
119 base::Unretained(this))),
120 cursor_(cursor),
121 input_controller_(&keyboard_, &button_map_),
122 initialized_(false),
123 weak_ptr_factory_(this) {
124 DCHECK(device_manager_);
127 EventFactoryEvdev::~EventFactoryEvdev() {
130 void EventFactoryEvdev::Init() {
131 DCHECK(!initialized_);
133 StartThread();
135 initialized_ = true;
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;
170 switch (button) {
171 case BTN_LEFT:
172 modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
173 break;
174 case BTN_RIGHT:
175 modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
176 break;
177 case BTN_MIDDLE:
178 modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
179 break;
180 default:
181 return;
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,
221 &y);
222 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
223 &radius_x);
224 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
225 &radius_y);
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)
272 return;
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());
279 break;
281 case DeviceEvent::REMOVE: {
282 TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", event.path().value());
283 input_device_factory_proxy_->RemoveInputDevice(event.path());
284 break;
289 void EventFactoryEvdev::OnDispatcherListChanged() {
290 if (!initialized_)
291 Init();
294 void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget,
295 const gfx::PointF& location) {
296 if (!cursor_)
297 return;
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);
334 } // namespace ui