Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / events / ozone / evdev / tablet_event_converter_evdev.cc
blob24b01fcf0ac0fcf20f994e84e9ab1f34d9600514
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/tablet_event_converter_evdev.h"
7 #include <errno.h>
8 #include <linux/input.h>
10 #include "base/message_loop/message_loop.h"
11 #include "ui/events/event.h"
12 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
14 namespace ui {
16 TabletEventConverterEvdev::TabletEventConverterEvdev(
17 int fd,
18 base::FilePath path,
19 int id,
20 InputDeviceType type,
21 CursorDelegateEvdev* cursor,
22 const EventDeviceInfo& info,
23 DeviceEventDispatcherEvdev* dispatcher)
24 : EventConverterEvdev(fd, path, id, type),
25 cursor_(cursor),
26 dispatcher_(dispatcher),
27 stylus_(0),
28 abs_value_dirty_(false) {
29 x_abs_min_ = info.GetAbsMinimum(ABS_X);
30 x_abs_range_ = info.GetAbsMaximum(ABS_X) - x_abs_min_ + 1;
31 y_abs_min_ = info.GetAbsMinimum(ABS_Y);
32 y_abs_range_ = info.GetAbsMaximum(ABS_Y) - y_abs_min_ + 1;
35 TabletEventConverterEvdev::~TabletEventConverterEvdev() {
36 Stop();
37 close(fd_);
40 void TabletEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) {
41 input_event inputs[4];
42 ssize_t read_size = read(fd, inputs, sizeof(inputs));
43 if (read_size < 0) {
44 if (errno == EINTR || errno == EAGAIN)
45 return;
46 if (errno != ENODEV)
47 PLOG(ERROR) << "error reading device " << path_.value();
48 Stop();
49 return;
52 if (ignore_events_)
53 return;
55 DCHECK_EQ(read_size % sizeof(*inputs), 0u);
56 ProcessEvents(inputs, read_size / sizeof(*inputs));
59 void TabletEventConverterEvdev::ProcessEvents(const input_event* inputs,
60 int count) {
61 for (int i = 0; i < count; ++i) {
62 const input_event& input = inputs[i];
63 switch (input.type) {
64 case EV_KEY:
65 ConvertKeyEvent(input);
66 break;
67 case EV_ABS:
68 ConvertAbsEvent(input);
69 break;
70 case EV_SYN:
71 FlushEvents(input);
72 break;
77 void TabletEventConverterEvdev::ConvertKeyEvent(const input_event& input) {
78 // Only handle other events if we have a stylus in proximity
79 if (input.code >= BTN_TOOL_PEN && input.code <= BTN_TOOL_LENS) {
80 if (input.value == 1)
81 stylus_ = input.code;
82 else if (input.value == 0)
83 stylus_ = 0;
84 else
85 LOG(WARNING) << "Unexpected value: " << input.value
86 << " for code: " << input.code;
89 if (input.code >= BTN_TOUCH && input.code <= BTN_STYLUS2) {
90 DispatchMouseButton(input);
91 return;
95 void TabletEventConverterEvdev::ConvertAbsEvent(const input_event& input) {
96 if (!cursor_)
97 return;
99 switch (input.code) {
100 case ABS_X:
101 x_abs_location_ = input.value;
102 abs_value_dirty_ = true;
103 break;
104 case ABS_Y:
105 y_abs_location_ = input.value;
106 abs_value_dirty_ = true;
107 break;
111 void TabletEventConverterEvdev::UpdateCursor() {
112 gfx::Rect confined_bounds = cursor_->GetCursorConfinedBounds();
114 int x =
115 ((x_abs_location_ - x_abs_min_) * confined_bounds.width()) / x_abs_range_;
116 int y = ((y_abs_location_ - y_abs_min_) * confined_bounds.height()) /
117 y_abs_range_;
119 x += confined_bounds.x();
120 y += confined_bounds.y();
122 cursor_->MoveCursorTo(gfx::PointF(x, y));
125 void TabletEventConverterEvdev::DispatchMouseButton(const input_event& input) {
126 if (!cursor_)
127 return;
129 unsigned int button;
130 // These are the same as X11 behaviour
131 if (input.code == BTN_TOUCH)
132 button = BTN_LEFT;
133 else if (input.code == BTN_STYLUS2)
134 button = BTN_RIGHT;
135 else if (input.code == BTN_STYLUS)
136 button = BTN_MIDDLE;
137 else
138 return;
140 if (abs_value_dirty_) {
141 UpdateCursor();
142 abs_value_dirty_ = false;
145 bool down = input.value;
147 dispatcher_->DispatchMouseButtonEvent(MouseButtonEventParams(
148 id_, cursor_->GetLocation(), button, down, false /* allow_remap */,
149 TimeDeltaFromInputEvent(input)));
152 void TabletEventConverterEvdev::FlushEvents(const input_event& input) {
153 if (!cursor_)
154 return;
156 // Prevent propagation of invalid data on stylus lift off
157 if (stylus_ == 0) {
158 abs_value_dirty_ = false;
159 return;
162 if (!abs_value_dirty_)
163 return;
165 UpdateCursor();
167 dispatcher_->DispatchMouseMoveEvent(MouseMoveEventParams(
168 id_, cursor_->GetLocation(), TimeDeltaFromInputEvent(input)));
170 abs_value_dirty_ = false;
173 } // namespace ui