#include "base/debug/trace_event.h"
#include "base/stl_util.h"
#include "base/task_runner.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/device_manager_evdev.h"
#include "ui/events/ozone/evdev/event_device_info.h"
#include "ui/events/ozone/evdev/key_event_converter_evdev.h"
#include "ui/events/ozone/evdev/touch_event_converter_evdev.h"
-#if defined(USE_UDEV)
-#include "ui/events/ozone/evdev/device_manager_udev.h"
+#if defined(USE_EVDEV_GESTURES)
+#include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h"
+#include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
#endif
#ifndef EVIOCSCLOCKID
namespace {
-bool IsTouchPad(const EventDeviceInfo& devinfo) {
- if (!devinfo.HasEventType(EV_ABS))
- return false;
+#if defined(USE_EVDEV_GESTURES)
+bool UseGesturesLibraryForDevice(const EventDeviceInfo& devinfo) {
+ if (devinfo.HasAbsXY() && !devinfo.IsMappedToScreen())
+ return true; // touchpad
- return devinfo.HasKeyEvent(BTN_LEFT) || devinfo.HasKeyEvent(BTN_MIDDLE) ||
- devinfo.HasKeyEvent(BTN_RIGHT) || devinfo.HasKeyEvent(BTN_TOOL_FINGER);
+ if (devinfo.HasRelXY())
+ return true; // mouse
+
+ return false;
}
+#endif
+
+scoped_ptr<EventConverterEvdev> CreateConverter(
+ int fd,
+ const base::FilePath& path,
+ const EventDeviceInfo& devinfo,
+ const EventDispatchCallback& dispatch,
+ EventModifiersEvdev* modifiers,
+ CursorDelegateEvdev* cursor) {
+#if defined(USE_EVDEV_GESTURES)
+ // Touchpad or mouse: use gestures library.
+ // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent
+ if (UseGesturesLibraryForDevice(devinfo)) {
+ scoped_ptr<GestureInterpreterLibevdevCros> gesture_interp = make_scoped_ptr(
+ new GestureInterpreterLibevdevCros(modifiers, cursor, dispatch));
+ scoped_ptr<EventReaderLibevdevCros> libevdev_reader =
+ make_scoped_ptr(new EventReaderLibevdevCros(
+ fd,
+ path,
+ gesture_interp.PassAs<EventReaderLibevdevCros::Delegate>()));
+ return libevdev_reader.PassAs<EventConverterEvdev>();
+ }
+#endif
-bool IsTouchScreen(const EventDeviceInfo& devinfo) {
- return devinfo.HasEventType(EV_ABS) && !IsTouchPad(devinfo);
+ // Touchscreen: use TouchEventConverterEvdev.
+ scoped_ptr<EventConverterEvdev> converter;
+ if (devinfo.HasAbsXY())
+ return make_scoped_ptr<EventConverterEvdev>(
+ new TouchEventConverterEvdev(fd, path, devinfo, dispatch));
+
+ // Everything else: use KeyEventConverterEvdev.
+ return make_scoped_ptr<EventConverterEvdev>(
+ new KeyEventConverterEvdev(fd, path, modifiers, dispatch));
}
// Open an input device. Opening may put the calling thread to sleep, and
EventModifiersEvdev* modifiers,
CursorDelegateEvdev* cursor,
scoped_refptr<base::TaskRunner> reply_runner,
+ const EventDispatchCallback& dispatch,
base::Callback<void(scoped_ptr<EventConverterEvdev>)> reply_callback) {
TRACE_EVENT1("ozone", "OpenInputDevice", "path", path.value());
return;
}
- if (IsTouchPad(devinfo)) {
- LOG(WARNING) << "touchpad device not supported: " << path.value();
- close(fd);
- return;
- }
-
- // TODO(spang) Add more device types.
- scoped_ptr<EventConverterEvdev> converter;
- if (IsTouchScreen(devinfo))
- converter.reset(new TouchEventConverterEvdev(fd, path, devinfo));
- else if (devinfo.HasEventType(EV_KEY))
- converter.reset(new KeyEventConverterEvdev(fd, path, modifiers));
+ scoped_ptr<EventConverterEvdev> converter =
+ CreateConverter(fd, path, devinfo, dispatch, modifiers, cursor);
- if (converter) {
- // Reply with the constructed converter.
- reply_runner->PostTask(
- FROM_HERE, base::Bind(reply_callback, base::Passed(&converter)));
- } else {
- close(fd);
- }
+ // Reply with the constructed converter.
+ reply_runner->PostTask(FROM_HERE,
+ base::Bind(reply_callback, base::Passed(&converter)));
}
// Close an input device. Closing may put the calling thread to sleep, and
} // namespace
EventFactoryEvdev::EventFactoryEvdev()
- : ui_task_runner_(base::MessageLoopProxy::current()),
+ : device_manager_(NULL),
+ has_started_processing_events_(false),
+ ui_task_runner_(base::MessageLoopProxy::current()),
file_task_runner_(base::MessageLoopProxy::current()),
cursor_(NULL),
+ dispatch_callback_(
+ base::Bind(base::IgnoreResult(&EventFactoryEvdev::DispatchUiEvent),
+ base::Unretained(this))),
weak_ptr_factory_(this) {}
-EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor)
- : ui_task_runner_(base::MessageLoopProxy::current()),
+EventFactoryEvdev::EventFactoryEvdev(
+ CursorDelegateEvdev* cursor,
+ DeviceManager* device_manager)
+ : device_manager_(device_manager),
+ has_started_processing_events_(false),
+ ui_task_runner_(base::MessageLoopProxy::current()),
file_task_runner_(base::MessageLoopProxy::current()),
cursor_(cursor),
+ dispatch_callback_(
+ base::Bind(base::IgnoreResult(&EventFactoryEvdev::DispatchUiEvent),
+ base::Unretained(this))),
weak_ptr_factory_(this) {}
EventFactoryEvdev::~EventFactoryEvdev() { STLDeleteValues(&converters_); }
+void EventFactoryEvdev::DispatchUiEvent(Event* event) {
+ EventFactoryOzone::DispatchEvent(event);
+}
+
void EventFactoryEvdev::AttachInputDevice(
const base::FilePath& path,
scoped_ptr<EventConverterEvdev> converter) {
converters_[path]->Start();
}
-void EventFactoryEvdev::OnDeviceAdded(const base::FilePath& path) {
- TRACE_EVENT1("ozone", "OnDeviceAdded", "path", path.value());
-
- // Dispatch task to open on FILE thread, since open may block.
- file_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&OpenInputDevice,
- path,
- &modifiers_,
- cursor_,
- ui_task_runner_,
- base::Bind(&EventFactoryEvdev::AttachInputDevice,
- weak_ptr_factory_.GetWeakPtr(),
- path)));
+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("ozone", "OnDeviceAdded", "path", event.path().value());
+
+ // Dispatch task to open on FILE thread, since open may block.
+ file_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&OpenInputDevice,
+ event.path(),
+ &modifiers_,
+ cursor_,
+ ui_task_runner_,
+ dispatch_callback_,
+ base::Bind(&EventFactoryEvdev::AttachInputDevice,
+ weak_ptr_factory_.GetWeakPtr(),
+ event.path())));
+ }
+ break;
+ case DeviceEvent::REMOVE: {
+ TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", event.path().value());
+ DetachInputDevice(event.path());
+ }
+ break;
+ }
}
void EventFactoryEvdev::DetachInputDevice(const base::FilePath& path) {
}
}
-void EventFactoryEvdev::OnDeviceRemoved(const base::FilePath& path) {
- TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", path.value());
- DetachInputDevice(path);
-}
-
void EventFactoryEvdev::StartProcessingEvents() {
CHECK(ui_task_runner_->RunsTasksOnCurrentThread());
-#if defined(USE_UDEV)
- // Scan for input devices using udev.
- device_manager_ = CreateDeviceManagerUdev();
-#else
- // No udev support. Scan devices manually in /dev/input.
- device_manager_ = CreateDeviceManagerManual();
-#endif
-
- // Scan & monitor devices.
- device_manager_->ScanAndStartMonitoring(
- base::Bind(&EventFactoryEvdev::OnDeviceAdded, base::Unretained(this)),
- base::Bind(&EventFactoryEvdev::OnDeviceRemoved, base::Unretained(this)));
+ if (device_manager_ && !has_started_processing_events_) {
+ has_started_processing_events_ = true;
+ // Scan & monitor devices.
+ device_manager_->AddObserver(this);
+ device_manager_->ScanDevices(this);
+ }
}
void EventFactoryEvdev::SetFileTaskRunner(
const gfx::PointF& location) {
if (cursor_) {
cursor_->MoveCursorTo(widget, location);
- scoped_ptr<Event> ev(new MouseEvent(ET_MOUSE_MOVED,
- cursor_->location(),
- cursor_->location(),
- modifiers_.GetModifierFlags(),
- /* changed_button_flags */ 0));
- DispatchEvent(ev.Pass());
+ MouseEvent mouse_event(ET_MOUSE_MOVED,
+ cursor_->location(),
+ cursor_->location(),
+ modifiers_.GetModifierFlags(),
+ /* changed_button_flags */ 0);
+ DispatchEvent(&mouse_event);
}
}