| Index: ui/events/ozone/evdev/event_factory_evdev.cc
|
| diff --git a/ui/events/ozone/evdev/event_factory_evdev.cc b/ui/events/ozone/evdev/event_factory_evdev.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9d79b14b0483ff6eb4ab0c7342b72dd4d323d126
|
| --- /dev/null
|
| +++ b/ui/events/ozone/evdev/event_factory_evdev.cc
|
| @@ -0,0 +1,393 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ui/events/ozone/evdev/event_factory_evdev.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/task_runner.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| +#include "base/threading/worker_pool.h"
|
| +#include "base/time/time.h"
|
| +#include "base/trace_event/trace_event.h"
|
| +#include "ui/events/devices/device_data_manager.h"
|
| +#include "ui/events/devices/input_device.h"
|
| +#include "ui/events/event_utils.h"
|
| +#include "ui/events/ozone/device/device_event.h"
|
| +#include "ui/events/ozone/device/device_manager.h"
|
| +#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
|
| +#include "ui/events/ozone/evdev/input_controller_evdev.h"
|
| +#include "ui/events/ozone/evdev/input_device_factory_evdev.h"
|
| +#include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
|
| +#include "ui/events/ozone/evdev/input_injector_evdev.h"
|
| +#include "ui/events/ozone/evdev/touch_evdev_types.h"
|
| +
|
| +namespace ui {
|
| +
|
| +namespace {
|
| +
|
| +// Thread safe dispatcher proxy for EventFactoryEvdev.
|
| +//
|
| +// This is used on the device I/O thread for dispatching to UI.
|
| +class ProxyDeviceEventDispatcher : public DeviceEventDispatcherEvdev {
|
| + public:
|
| + ProxyDeviceEventDispatcher(
|
| + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner,
|
| + base::WeakPtr<EventFactoryEvdev> event_factory_evdev)
|
| + : ui_thread_runner_(ui_thread_runner),
|
| + event_factory_evdev_(event_factory_evdev) {}
|
| + ~ProxyDeviceEventDispatcher() override {}
|
| +
|
| + // DeviceEventDispatcher:
|
| + void DispatchKeyEvent(const KeyEventParams& params) override {
|
| + ui_thread_runner_->PostTask(FROM_HERE,
|
| + base::Bind(&EventFactoryEvdev::DispatchKeyEvent,
|
| + event_factory_evdev_, params));
|
| + }
|
| +
|
| + void DispatchMouseMoveEvent(const MouseMoveEventParams& params) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent,
|
| + event_factory_evdev_, params));
|
| + }
|
| +
|
| + void DispatchMouseButtonEvent(const MouseButtonEventParams& params) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseButtonEvent,
|
| + event_factory_evdev_, params));
|
| + }
|
| +
|
| + void DispatchMouseWheelEvent(const MouseWheelEventParams& params) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseWheelEvent,
|
| + event_factory_evdev_, params));
|
| + }
|
| +
|
| + void DispatchScrollEvent(const ScrollEventParams& params) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchScrollEvent,
|
| + event_factory_evdev_, params));
|
| + }
|
| +
|
| + void DispatchTouchEvent(const TouchEventParams& params) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchTouchEvent,
|
| + event_factory_evdev_, params));
|
| + }
|
| +
|
| + void DispatchKeyboardDevicesUpdated(
|
| + const std::vector<KeyboardDevice>& devices) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&EventFactoryEvdev::DispatchKeyboardDevicesUpdated,
|
| + event_factory_evdev_, devices));
|
| + }
|
| + void DispatchTouchscreenDevicesUpdated(
|
| + const std::vector<TouchscreenDevice>& devices) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&EventFactoryEvdev::DispatchTouchscreenDevicesUpdated,
|
| + event_factory_evdev_, devices));
|
| + }
|
| + void DispatchMouseDevicesUpdated(
|
| + const std::vector<InputDevice>& devices) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseDevicesUpdated,
|
| + event_factory_evdev_, devices));
|
| + }
|
| + void DispatchTouchpadDevicesUpdated(
|
| + const std::vector<InputDevice>& devices) override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&EventFactoryEvdev::DispatchTouchpadDevicesUpdated,
|
| + event_factory_evdev_, devices));
|
| + }
|
| + void DispatchDeviceListsComplete() override {
|
| + ui_thread_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchDeviceListsComplete,
|
| + event_factory_evdev_));
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner_;
|
| + base::WeakPtr<EventFactoryEvdev> event_factory_evdev_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor,
|
| + DeviceManager* device_manager,
|
| + KeyboardLayoutEngine* keyboard_layout)
|
| + : device_manager_(device_manager),
|
| + keyboard_(&modifiers_,
|
| + keyboard_layout,
|
| + base::Bind(&EventFactoryEvdev::DispatchUiEvent,
|
| + base::Unretained(this))),
|
| + cursor_(cursor),
|
| + input_controller_(&keyboard_, &button_map_),
|
| + touch_id_generator_(0),
|
| + weak_ptr_factory_(this) {
|
| + DCHECK(device_manager_);
|
| +}
|
| +
|
| +EventFactoryEvdev::~EventFactoryEvdev() {
|
| +}
|
| +
|
| +void EventFactoryEvdev::Init() {
|
| + DCHECK(!initialized_);
|
| +
|
| + StartThread();
|
| +
|
| + initialized_ = true;
|
| +}
|
| +
|
| +scoped_ptr<SystemInputInjector> EventFactoryEvdev::CreateSystemInputInjector() {
|
| + // Use forwarding dispatcher for the injector rather than dispatching
|
| + // directly. We cannot assume it is safe to (re-)enter ui::Event dispatch
|
| + // synchronously from the injection point.
|
| + scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher(
|
| + new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| + return make_scoped_ptr(
|
| + new InputInjectorEvdev(proxy_dispatcher.Pass(), cursor_));
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchKeyEvent(const KeyEventParams& params) {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchKeyEvent", "device",
|
| + params.device_id);
|
| + keyboard_.OnKeyChange(params.code, params.down, params.suppress_auto_repeat,
|
| + params.timestamp, params.device_id);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchMouseMoveEvent(
|
| + const MouseMoveEventParams& params) {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseMoveEvent", "device",
|
| + params.device_id);
|
| + MouseEvent event(ui::ET_MOUSE_MOVED, params.location, params.location,
|
| + params.timestamp, modifiers_.GetModifierFlags(),
|
| + /* changed_button_flags */ 0);
|
| + event.set_source_device_id(params.device_id);
|
| + DispatchUiEvent(&event);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchMouseButtonEvent(
|
| + const MouseButtonEventParams& params) {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseButtonEvent", "device",
|
| + params.device_id);
|
| +
|
| + // Mouse buttons can be remapped, touchpad taps & clicks cannot.
|
| + unsigned int button = params.button;
|
| + if (params.allow_remap)
|
| + button = button_map_.GetMappedButton(button);
|
| +
|
| + int modifier = EVDEV_MODIFIER_NONE;
|
| + switch (button) {
|
| + case BTN_LEFT:
|
| + modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
|
| + break;
|
| + case BTN_RIGHT:
|
| + modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
|
| + break;
|
| + case BTN_MIDDLE:
|
| + modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
|
| + break;
|
| + case BTN_BACK:
|
| + modifier = EVDEV_MODIFIER_BACK_MOUSE_BUTTON;
|
| + break;
|
| + case BTN_FORWARD:
|
| + modifier = EVDEV_MODIFIER_FORWARD_MOUSE_BUTTON;
|
| + break;
|
| + default:
|
| + return;
|
| + }
|
| +
|
| + int flag = modifiers_.GetEventFlagFromModifier(modifier);
|
| + bool was_down = modifiers_.GetModifierFlags() & flag;
|
| + modifiers_.UpdateModifier(modifier, params.down);
|
| + bool down = modifiers_.GetModifierFlags() & flag;
|
| +
|
| + // Suppress nested clicks. EventModifiersEvdev counts presses, we only
|
| + // dispatch an event on 0-1 (first press) and 1-0 (last release) transitions.
|
| + if (down == was_down)
|
| + return;
|
| +
|
| + MouseEvent event(params.down ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED,
|
| + params.location, params.location, params.timestamp,
|
| + modifiers_.GetModifierFlags() | flag,
|
| + /* changed_button_flags */ flag);
|
| + event.set_source_device_id(params.device_id);
|
| + DispatchUiEvent(&event);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchMouseWheelEvent(
|
| + const MouseWheelEventParams& params) {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseWheelEvent", "device",
|
| + params.device_id);
|
| + MouseWheelEvent event(params.delta, params.location, params.location,
|
| + params.timestamp, modifiers_.GetModifierFlags(),
|
| + 0 /* changed_button_flags */);
|
| + event.set_source_device_id(params.device_id);
|
| + DispatchUiEvent(&event);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchScrollEvent(const ScrollEventParams& params) {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchScrollEvent", "device",
|
| + params.device_id);
|
| + ScrollEvent event(params.type, params.location, params.timestamp,
|
| + modifiers_.GetModifierFlags(), params.delta.x(),
|
| + params.delta.y(), params.ordinal_delta.x(),
|
| + params.ordinal_delta.y(), params.finger_count);
|
| + event.set_source_device_id(params.device_id);
|
| + DispatchUiEvent(&event);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams& params) {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchTouchEvent", "device",
|
| + params.device_id);
|
| +
|
| + float x = params.location.x();
|
| + float y = params.location.y();
|
| + double radius_x = params.radii.x();
|
| + double radius_y = params.radii.y();
|
| +
|
| + // Transform the event to align touches to the image based on display mode.
|
| + DeviceDataManager::GetInstance()->ApplyTouchTransformer(params.device_id, &x,
|
| + &y);
|
| + DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
|
| + &radius_x);
|
| + DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
|
| + &radius_y);
|
| +
|
| + // params.slot is guaranteed to be < kNumTouchEvdevSlots.
|
| + int touch_id = touch_id_generator_.GetGeneratedID(
|
| + params.device_id * kNumTouchEvdevSlots + params.slot);
|
| + TouchEvent touch_event(params.type, gfx::PointF(x, y),
|
| + modifiers_.GetModifierFlags(), touch_id,
|
| + params.timestamp, radius_x, radius_y,
|
| + /* angle */ 0.f, params.pressure);
|
| + touch_event.set_source_device_id(params.device_id);
|
| + DispatchUiEvent(&touch_event);
|
| +
|
| + if (params.type == ET_TOUCH_RELEASED || params.type == ET_TOUCH_CANCELLED) {
|
| + touch_id_generator_.ReleaseGeneratedID(touch_event.touch_id());
|
| + }
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchUiEvent(Event* event) {
|
| + // DispatchEvent takes PlatformEvent which is void*. This function
|
| + // wraps it with the real type.
|
| + DispatchEvent(event);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchKeyboardDevicesUpdated(
|
| + const std::vector<KeyboardDevice>& devices) {
|
| + TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchKeyboardDevicesUpdated");
|
| + DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
|
| + observer->OnKeyboardDevicesUpdated(devices);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchTouchscreenDevicesUpdated(
|
| + const std::vector<TouchscreenDevice>& devices) {
|
| + TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchscreenDevicesUpdated");
|
| + DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
|
| + observer->OnTouchscreenDevicesUpdated(devices);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchMouseDevicesUpdated(
|
| + const std::vector<InputDevice>& devices) {
|
| + TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchMouseDevicesUpdated");
|
| +
|
| + // There's no list of mice in DeviceDataManager.
|
| + input_controller_.set_has_mouse(devices.size() != 0);
|
| + DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
|
| + observer->OnMouseDevicesUpdated(devices);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchTouchpadDevicesUpdated(
|
| + const std::vector<InputDevice>& devices) {
|
| + TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchpadDevicesUpdated");
|
| +
|
| + // There's no list of touchpads in DeviceDataManager.
|
| + input_controller_.set_has_touchpad(devices.size() != 0);
|
| + DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
|
| + observer->OnTouchpadDevicesUpdated(devices);
|
| +}
|
| +
|
| +void EventFactoryEvdev::DispatchDeviceListsComplete() {
|
| + TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchDeviceListsComplete");
|
| + DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
|
| + observer->OnDeviceListsComplete();
|
| +}
|
| +
|
| +void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent& event) {
|
| + if (event.device_type() != DeviceEvent::INPUT)
|
| + return;
|
| +
|
| + switch (event.action_type()) {
|
| + case DeviceEvent::ADD:
|
| + case DeviceEvent::CHANGE: {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceAdded", "path",
|
| + event.path().value());
|
| + input_device_factory_proxy_->AddInputDevice(NextDeviceId(), event.path());
|
| + break;
|
| + }
|
| + case DeviceEvent::REMOVE: {
|
| + TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceRemoved", "path",
|
| + event.path().value());
|
| + input_device_factory_proxy_->RemoveInputDevice(event.path());
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void EventFactoryEvdev::OnDispatcherListChanged() {
|
| + if (!initialized_)
|
| + Init();
|
| +}
|
| +
|
| +void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget,
|
| + const gfx::PointF& location) {
|
| + if (!cursor_)
|
| + return;
|
| +
|
| + cursor_->MoveCursorTo(widget, location);
|
| +
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| + FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + MouseMoveEventParams(-1 /* device_id */,
|
| + cursor_->GetLocation(),
|
| + EventTimeForNow())));
|
| +}
|
| +
|
| +int EventFactoryEvdev::NextDeviceId() {
|
| + return ++last_device_id_;
|
| +}
|
| +
|
| +void EventFactoryEvdev::StartThread() {
|
| + // Set up device factory.
|
| + scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher(
|
| + new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| + thread_.Start(proxy_dispatcher.Pass(), cursor_,
|
| + base::Bind(&EventFactoryEvdev::OnThreadStarted,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void EventFactoryEvdev::OnThreadStarted(
|
| + scoped_ptr<InputDeviceFactoryEvdevProxy> input_device_factory) {
|
| + TRACE_EVENT0("evdev", "EventFactoryEvdev::OnThreadStarted");
|
| + input_device_factory_proxy_ = input_device_factory.Pass();
|
| +
|
| + // Hook up device configuration.
|
| + input_controller_.SetInputDeviceFactory(input_device_factory_proxy_.get());
|
| +
|
| + // Scan & monitor devices.
|
| + device_manager_->AddObserver(this);
|
| + device_manager_->ScanDevices(this);
|
| +
|
| + // Notify device thread that initial scan is done.
|
| + input_device_factory_proxy_->OnStartupScanComplete();
|
| +}
|
| +
|
| +} // namespace ui
|
|
|