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"
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"
17 TabletEventConverterEvdev::TabletEventConverterEvdev(
21 CursorDelegateEvdev
* cursor
,
22 const EventDeviceInfo
& info
,
23 DeviceEventDispatcherEvdev
* dispatcher
)
24 : EventConverterEvdev(fd
,
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
) {
48 "TabletEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd",
51 input_event inputs
[4];
52 ssize_t read_size
= read(fd
, inputs
, sizeof(inputs
));
54 if (errno
== EINTR
|| errno
== EAGAIN
)
57 PLOG(ERROR
) << "error reading device " << path_
.value();
65 DCHECK_EQ(read_size
% sizeof(*inputs
), 0u);
66 ProcessEvents(inputs
, read_size
/ sizeof(*inputs
));
69 void TabletEventConverterEvdev::ProcessEvents(const input_event
* inputs
,
71 for (int i
= 0; i
< count
; ++i
) {
72 const input_event
& input
= inputs
[i
];
75 ConvertKeyEvent(input
);
78 ConvertAbsEvent(input
);
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
) {
92 else if (input
.value
== 0)
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
);
105 void TabletEventConverterEvdev::ConvertAbsEvent(const input_event
& input
) {
109 switch (input
.code
) {
111 x_abs_location_
= input
.value
;
112 abs_value_dirty_
= true;
115 y_abs_location_
= input
.value
;
116 abs_value_dirty_
= true;
119 tilt_x_
= (90.0f
* input
.value
) / tilt_x_max_
;
120 abs_value_dirty_
= true;
123 tilt_y_
= (90.0f
* input
.value
) / tilt_y_max_
;
124 abs_value_dirty_
= true;
127 pressure_
= (float)input
.value
/ pressure_max_
;
128 abs_value_dirty_
= true;
133 void TabletEventConverterEvdev::UpdateCursor() {
134 gfx::Rect confined_bounds
= cursor_
->GetCursorConfinedBounds();
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()) /
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
) {
152 // These are the same as X11 behaviour
153 if (input
.code
== BTN_TOUCH
)
155 else if (input
.code
== BTN_STYLUS2
)
157 else if (input
.code
== BTN_STYLUS
)
162 if (abs_value_dirty_
) {
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_
,
175 TimeDeltaFromInputEvent(input
)));
178 void TabletEventConverterEvdev::FlushEvents(const input_event
& input
) {
182 // Prevent propagation of invalid data on stylus lift off
184 abs_value_dirty_
= false;
188 if (!abs_value_dirty_
)
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_
,
198 TimeDeltaFromInputEvent(input
)));
200 abs_value_dirty_
= false;