Update V8 to version 4.7.16.
[chromium-blink-merge.git] / ui / events / ozone / evdev / tablet_event_converter_evdev.cc
blob00fd5070da8bbae16cd1939f034757c420375900
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 "base/trace_event/trace_event.h"
12 #include "ui/events/event.h"
13 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
15 namespace ui {
17 TabletEventConverterEvdev::TabletEventConverterEvdev(
18 int fd,
19 base::FilePath path,
20 int id,
21 CursorDelegateEvdev* cursor,
22 const EventDeviceInfo& info,
23 DeviceEventDispatcherEvdev* dispatcher)
24 : EventConverterEvdev(fd,
25 path,
26 id,
27 info.device_type(),
28 info.name(),
29 info.vendor_id(),
30 info.product_id()),
31 cursor_(cursor),
32 dispatcher_(dispatcher) {
33 x_abs_min_ = info.GetAbsMinimum(ABS_X);
34 x_abs_range_ = info.GetAbsMaximum(ABS_X) - x_abs_min_ + 1;
35 y_abs_min_ = info.GetAbsMinimum(ABS_Y);
36 y_abs_range_ = info.GetAbsMaximum(ABS_Y) - y_abs_min_ + 1;
38 tilt_x_max_ = info.GetAbsMaximum(ABS_TILT_X);
39 tilt_y_max_ = info.GetAbsMaximum(ABS_TILT_Y);
40 pressure_max_ = info.GetAbsMaximum(ABS_PRESSURE);
43 TabletEventConverterEvdev::~TabletEventConverterEvdev() {
46 void TabletEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) {
47 TRACE_EVENT1("evdev",
48 "TabletEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd",
49 fd);
51 input_event inputs[4];
52 ssize_t read_size = read(fd, inputs, sizeof(inputs));
53 if (read_size < 0) {
54 if (errno == EINTR || errno == EAGAIN)
55 return;
56 if (errno != ENODEV)
57 PLOG(ERROR) << "error reading device " << path_.value();
58 Stop();
59 return;
62 if (!enabled_)
63 return;
65 DCHECK_EQ(read_size % sizeof(*inputs), 0u);
66 ProcessEvents(inputs, read_size / sizeof(*inputs));
69 void TabletEventConverterEvdev::ProcessEvents(const input_event* inputs,
70 int count) {
71 for (int i = 0; i < count; ++i) {
72 const input_event& input = inputs[i];
73 switch (input.type) {
74 case EV_KEY:
75 ConvertKeyEvent(input);
76 break;
77 case EV_ABS:
78 ConvertAbsEvent(input);
79 break;
80 case EV_SYN:
81 FlushEvents(input);
82 break;
87 void TabletEventConverterEvdev::ConvertKeyEvent(const input_event& input) {
88 // Only handle other events if we have a stylus in proximity
89 if (input.code >= BTN_TOOL_PEN && input.code <= BTN_TOOL_LENS) {
90 if (input.value == 1)
91 stylus_ = input.code;
92 else if (input.value == 0)
93 stylus_ = 0;
94 else
95 LOG(WARNING) << "Unexpected value: " << input.value
96 << " for code: " << input.code;
99 if (input.code >= BTN_TOUCH && input.code <= BTN_STYLUS2) {
100 DispatchMouseButton(input);
101 return;
105 void TabletEventConverterEvdev::ConvertAbsEvent(const input_event& input) {
106 if (!cursor_)
107 return;
109 switch (input.code) {
110 case ABS_X:
111 x_abs_location_ = input.value;
112 abs_value_dirty_ = true;
113 break;
114 case ABS_Y:
115 y_abs_location_ = input.value;
116 abs_value_dirty_ = true;
117 break;
118 case ABS_TILT_X:
119 tilt_x_ = (90.0f * input.value) / tilt_x_max_;
120 abs_value_dirty_ = true;
121 break;
122 case ABS_TILT_Y:
123 tilt_y_ = (90.0f * input.value) / tilt_y_max_;
124 abs_value_dirty_ = true;
125 break;
126 case ABS_PRESSURE:
127 pressure_ = (float)input.value / pressure_max_;
128 abs_value_dirty_ = true;
129 break;
133 void TabletEventConverterEvdev::UpdateCursor() {
134 gfx::Rect confined_bounds = cursor_->GetCursorConfinedBounds();
136 int x =
137 ((x_abs_location_ - x_abs_min_) * confined_bounds.width()) / x_abs_range_;
138 int y = ((y_abs_location_ - y_abs_min_) * confined_bounds.height()) /
139 y_abs_range_;
141 x += confined_bounds.x();
142 y += confined_bounds.y();
144 cursor_->MoveCursorTo(gfx::PointF(x, y));
147 void TabletEventConverterEvdev::DispatchMouseButton(const input_event& input) {
148 if (!cursor_)
149 return;
151 unsigned int button;
152 // These are the same as X11 behaviour
153 if (input.code == BTN_TOUCH)
154 button = BTN_LEFT;
155 else if (input.code == BTN_STYLUS2)
156 button = BTN_RIGHT;
157 else if (input.code == BTN_STYLUS)
158 button = BTN_MIDDLE;
159 else
160 return;
162 if (abs_value_dirty_) {
163 UpdateCursor();
164 abs_value_dirty_ = false;
167 bool down = input.value;
169 dispatcher_->DispatchMouseButtonEvent(MouseButtonEventParams(
170 input_device_.id, cursor_->GetLocation(), button, down,
171 false /* allow_remap */,
172 PointerDetails(EventPointerType::POINTER_TYPE_PEN,
173 /* radius_x */ 0.0f, /* radius_y */ 0.0f, pressure_,
174 tilt_x_, tilt_y_),
175 TimeDeltaFromInputEvent(input)));
178 void TabletEventConverterEvdev::FlushEvents(const input_event& input) {
179 if (!cursor_)
180 return;
182 // Prevent propagation of invalid data on stylus lift off
183 if (stylus_ == 0) {
184 abs_value_dirty_ = false;
185 return;
188 if (!abs_value_dirty_)
189 return;
191 UpdateCursor();
193 dispatcher_->DispatchMouseMoveEvent(MouseMoveEventParams(
194 input_device_.id, cursor_->GetLocation(),
195 PointerDetails(EventPointerType::POINTER_TYPE_PEN,
196 /* radius_x */ 0.0f, /* radius_y */ 0.0f, pressure_,
197 tilt_x_, tilt_y_),
198 TimeDeltaFromInputEvent(input)));
200 abs_value_dirty_ = false;
203 } // namespace ui