blob: dc8e54b53d28affb0a8d9cf7231ab5fd409353c9 [file] [log] [blame]
// 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_converter_evdev_impl.h"
#include <errno.h>
#include <linux/input.h>
#include "base/message_loop/message_loop.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom4/keycode_converter.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace ui {
EventConverterEvdevImpl::EventConverterEvdevImpl(
int fd,
base::FilePath path,
int id,
EventModifiersEvdev* modifiers,
CursorDelegateEvdev* cursor,
KeyboardEvdev* keyboard,
const EventDispatchCallback& callback)
: EventConverterEvdev(fd, path, id),
x_offset_(0),
y_offset_(0),
cursor_(cursor),
keyboard_(keyboard),
modifiers_(modifiers),
callback_(callback) {
}
EventConverterEvdevImpl::~EventConverterEvdevImpl() {
Stop();
close(fd_);
}
void EventConverterEvdevImpl::OnFileCanReadWithoutBlocking(int fd) {
input_event inputs[4];
ssize_t read_size = read(fd, inputs, sizeof(inputs));
if (read_size < 0) {
if (errno == EINTR || errno == EAGAIN)
return;
if (errno != ENODEV)
PLOG(ERROR) << "error reading device " << path_.value();
Stop();
return;
}
DCHECK_EQ(read_size % sizeof(*inputs), 0u);
ProcessEvents(inputs, read_size / sizeof(*inputs));
}
void EventConverterEvdevImpl::ProcessEvents(const input_event* inputs,
int count) {
for (int i = 0; i < count; ++i) {
const input_event& input = inputs[i];
switch (input.type) {
case EV_KEY:
ConvertKeyEvent(input);
break;
case EV_REL:
ConvertMouseMoveEvent(input);
break;
case EV_SYN:
FlushEvents();
break;
}
}
}
void EventConverterEvdevImpl::ConvertKeyEvent(const input_event& input) {
// Mouse processing.
if (input.code >= BTN_MOUSE && input.code < BTN_JOYSTICK) {
DispatchMouseButton(input);
return;
}
// Keyboard processing.
keyboard_->OnKeyChange(input.code, input.value != 0);
}
void EventConverterEvdevImpl::ConvertMouseMoveEvent(const input_event& input) {
if (!cursor_)
return;
switch (input.code) {
case REL_X:
x_offset_ = input.value;
break;
case REL_Y:
y_offset_ = input.value;
break;
}
}
void EventConverterEvdevImpl::DispatchMouseButton(const input_event& input) {
if (!cursor_)
return;
unsigned int modifier;
if (input.code == BTN_LEFT)
modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
else if (input.code == BTN_RIGHT)
modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
else if (input.code == BTN_MIDDLE)
modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
else
return;
int flag = modifiers_->GetEventFlagFromModifier(modifier);
modifiers_->UpdateModifier(modifier, input.value);
callback_.Run(make_scoped_ptr(
new MouseEvent(input.value ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED,
cursor_->location(),
cursor_->location(),
modifiers_->GetModifierFlags() | flag,
flag)));
}
void EventConverterEvdevImpl::FlushEvents() {
if (!cursor_ || (x_offset_ == 0 && y_offset_ == 0))
return;
cursor_->MoveCursor(gfx::Vector2dF(x_offset_, y_offset_));
callback_.Run(make_scoped_ptr(
new MouseEvent(ui::ET_MOUSE_MOVED,
cursor_->location(),
cursor_->location(),
modifiers_->GetModifierFlags(),
/* changed_button_flags */ 0)));
x_offset_ = 0;
y_offset_ = 0;
}
} // namespace ui