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 "ui/events/event.h"
15 TabletEventConverterEvdev::TabletEventConverterEvdev(
20 EventModifiersEvdev
* modifiers
,
21 CursorDelegateEvdev
* cursor
,
22 const EventDeviceInfo
& info
,
23 const EventDispatchCallback
& callback
)
24 : EventConverterEvdev(fd
, path
, id
, type
),
26 modifiers_(modifiers
),
29 abs_value_dirty_(false) {
30 x_abs_min_
= info
.GetAbsMinimum(ABS_X
);
31 x_abs_range_
= info
.GetAbsMaximum(ABS_X
) - x_abs_min_
+ 1;
32 y_abs_min_
= info
.GetAbsMinimum(ABS_Y
);
33 y_abs_range_
= info
.GetAbsMaximum(ABS_Y
) - y_abs_min_
+ 1;
36 TabletEventConverterEvdev::~TabletEventConverterEvdev() {
41 void TabletEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd
) {
42 input_event inputs
[4];
43 ssize_t read_size
= read(fd
, inputs
, sizeof(inputs
));
45 if (errno
== EINTR
|| errno
== EAGAIN
)
48 PLOG(ERROR
) << "error reading device " << path_
.value();
53 DCHECK_EQ(read_size
% sizeof(*inputs
), 0u);
54 ProcessEvents(inputs
, read_size
/ sizeof(*inputs
));
57 void TabletEventConverterEvdev::ProcessEvents(const input_event
* inputs
,
59 for (int i
= 0; i
< count
; ++i
) {
60 const input_event
& input
= inputs
[i
];
63 ConvertKeyEvent(input
);
66 ConvertAbsEvent(input
);
75 void TabletEventConverterEvdev::ConvertKeyEvent(const input_event
& input
) {
76 // Only handle other events if we have a stylus in proximity
77 if (input
.code
>= BTN_TOOL_PEN
&& input
.code
<= BTN_TOOL_LENS
) {
80 else if (input
.value
== 0)
83 LOG(WARNING
) << "Unexpected value: " << input
.value
84 << " for code: " << input
.code
;
87 if (input
.code
>= BTN_TOUCH
&& input
.code
<= BTN_STYLUS2
) {
88 DispatchMouseButton(input
);
93 void TabletEventConverterEvdev::ConvertAbsEvent(const input_event
& input
) {
99 x_abs_location_
= input
.value
;
100 abs_value_dirty_
= true;
103 y_abs_location_
= input
.value
;
104 abs_value_dirty_
= true;
109 void TabletEventConverterEvdev::UpdateCursor() {
110 gfx::Rect display_bounds
= cursor_
->GetCursorDisplayBounds();
113 ((x_abs_location_
- x_abs_min_
) * display_bounds
.width()) / x_abs_range_
;
115 ((y_abs_location_
- y_abs_min_
) * display_bounds
.height()) / y_abs_range_
;
117 x
+= display_bounds
.x();
118 y
+= display_bounds
.y();
120 cursor_
->MoveCursorTo(gfx::PointF(x
, y
));
123 void TabletEventConverterEvdev::DispatchMouseButton(const input_event
& input
) {
127 unsigned int modifier
;
128 // These are the same as X11 behaviour
129 if (input
.code
== BTN_TOUCH
)
130 modifier
= EVDEV_MODIFIER_LEFT_MOUSE_BUTTON
;
131 else if (input
.code
== BTN_STYLUS2
)
132 modifier
= EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON
;
133 else if (input
.code
== BTN_STYLUS
)
134 modifier
= EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON
;
138 if (abs_value_dirty_
) {
140 abs_value_dirty_
= false;
143 int flag
= modifiers_
->GetEventFlagFromModifier(modifier
);
144 modifiers_
->UpdateModifier(modifier
, input
.value
);
145 callback_
.Run(make_scoped_ptr(
146 new MouseEvent(input
.value
? ET_MOUSE_PRESSED
: ET_MOUSE_RELEASED
,
147 cursor_
->GetLocation(), cursor_
->GetLocation(),
148 modifiers_
->GetModifierFlags() | flag
, flag
)));
151 void TabletEventConverterEvdev::FlushEvents() {
155 // Prevent propagation of invalid data on stylus lift off
157 abs_value_dirty_
= false;
161 if (!abs_value_dirty_
)
166 callback_
.Run(make_scoped_ptr(
167 new MouseEvent(ui::ET_MOUSE_MOVED
, cursor_
->GetLocation(),
168 cursor_
->GetLocation(), modifiers_
->GetModifierFlags(),
169 /* changed_button_flags */ 0)));
171 abs_value_dirty_
= false;