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/event_converter_evdev_impl.h"
8 #include <linux/input.h>
10 #include "base/trace_event/trace_event.h"
11 #include "ui/events/event.h"
12 #include "ui/events/event_utils.h"
13 #include "ui/events/keycodes/dom/keycode_converter.h"
14 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
15 #include "ui/events/ozone/evdev/keyboard_util_evdev.h"
22 const int kKeyReleaseValue
= 0;
23 const int kKeyRepeatValue
= 2;
27 EventConverterEvdevImpl::EventConverterEvdevImpl(
31 const EventDeviceInfo
& devinfo
,
32 CursorDelegateEvdev
* cursor
,
33 DeviceEventDispatcherEvdev
* dispatcher
)
34 : EventConverterEvdev(fd
,
37 devinfo
.device_type(),
40 devinfo
.product_id()),
41 has_keyboard_(devinfo
.HasKeyboard()),
42 has_touchpad_(devinfo
.HasTouchpad()),
43 has_caps_lock_led_(devinfo
.HasLedEvent(LED_CAPSL
)),
45 dispatcher_(dispatcher
) {
48 EventConverterEvdevImpl::~EventConverterEvdevImpl() {
53 void EventConverterEvdevImpl::OnFileCanReadWithoutBlocking(int fd
) {
54 TRACE_EVENT1("evdev", "EventConverterEvdevImpl::OnFileCanReadWithoutBlocking",
57 input_event inputs
[4];
58 ssize_t read_size
= read(fd
, inputs
, sizeof(inputs
));
60 if (errno
== EINTR
|| errno
== EAGAIN
)
63 PLOG(ERROR
) << "error reading device " << path_
.value();
71 DCHECK_EQ(read_size
% sizeof(*inputs
), 0u);
72 ProcessEvents(inputs
, read_size
/ sizeof(*inputs
));
75 bool EventConverterEvdevImpl::HasKeyboard() const {
79 bool EventConverterEvdevImpl::HasTouchpad() const {
83 bool EventConverterEvdevImpl::HasCapsLockLed() const {
84 return has_caps_lock_led_
;
87 void EventConverterEvdevImpl::SetKeyFilter(bool enable_filter
,
88 std::vector
<DomCode
> allowed_keys
) {
90 blocked_keys_
.reset();
95 for (const DomCode
& it
: allowed_keys
) {
97 NativeCodeToEvdevCode(KeycodeConverter::DomCodeToNativeKeycode(it
));
98 blocked_keys_
.reset(evdev_code
);
101 // Release any pressed blocked keys.
102 base::TimeDelta timestamp
= ui::EventTimeForNow();
103 for (int key
= 0; key
< KEY_CNT
; ++key
) {
104 if (blocked_keys_
.test(key
))
105 OnKeyChange(key
, false /* down */, timestamp
);
109 void EventConverterEvdevImpl::OnDisabled() {
111 ReleaseMouseButtons();
114 void EventConverterEvdevImpl::ProcessEvents(const input_event
* inputs
,
116 for (int i
= 0; i
< count
; ++i
) {
117 const input_event
& input
= inputs
[i
];
118 switch (input
.type
) {
120 ConvertKeyEvent(input
);
123 ConvertMouseMoveEvent(input
);
126 if (input
.code
== SYN_DROPPED
)
128 else if (input
.code
== SYN_REPORT
)
135 void EventConverterEvdevImpl::ConvertKeyEvent(const input_event
& input
) {
136 // Ignore repeat events.
137 if (input
.value
== kKeyRepeatValue
)
141 if (input
.code
>= BTN_MOUSE
&& input
.code
< BTN_JOYSTICK
) {
142 DispatchMouseButton(input
);
146 // Keyboard processing.
147 OnKeyChange(input
.code
, input
.value
!= kKeyReleaseValue
,
148 TimeDeltaFromInputEvent(input
));
151 void EventConverterEvdevImpl::ConvertMouseMoveEvent(const input_event
& input
) {
154 switch (input
.code
) {
156 x_offset_
= input
.value
;
159 y_offset_
= input
.value
;
164 void EventConverterEvdevImpl::OnKeyChange(unsigned int key
,
166 const base::TimeDelta
& timestamp
) {
170 if (down
== key_state_
.test(key
))
173 // Apply key filter (releases for previously pressed keys are excepted).
174 if (down
&& blocked_keys_
.test(key
))
177 // State transition: !(down) -> (down)
178 key_state_
.set(key
, down
);
180 dispatcher_
->DispatchKeyEvent(KeyEventParams(input_device_
.id
, key
, down
,
181 false /* suppress_auto_repeat */,
185 void EventConverterEvdevImpl::ReleaseKeys() {
186 base::TimeDelta timestamp
= ui::EventTimeForNow();
187 for (int key
= 0; key
< KEY_CNT
; ++key
)
188 OnKeyChange(key
, false /* down */, timestamp
);
191 void EventConverterEvdevImpl::ReleaseMouseButtons() {
192 base::TimeDelta timestamp
= ui::EventTimeForNow();
193 for (int code
= BTN_MOUSE
; code
< BTN_JOYSTICK
; ++code
)
194 OnButtonChange(code
, false /* down */, timestamp
);
197 void EventConverterEvdevImpl::OnLostSync() {
198 LOG(WARNING
) << "kernel dropped input events";
200 // We may have missed key releases. Release everything.
201 // TODO(spang): Use EVIOCGKEY to avoid releasing keys that are still held.
203 ReleaseMouseButtons();
206 void EventConverterEvdevImpl::DispatchMouseButton(const input_event
& input
) {
210 OnButtonChange(input
.code
, input
.value
, TimeDeltaFromInputEvent(input
));
213 void EventConverterEvdevImpl::OnButtonChange(int code
,
215 const base::TimeDelta
& timestamp
) {
216 if (code
== BTN_SIDE
)
218 else if (code
== BTN_EXTRA
)
221 int button_offset
= code
- BTN_MOUSE
;
222 if (mouse_button_state_
.test(button_offset
) == down
)
225 mouse_button_state_
.set(button_offset
, down
);
227 dispatcher_
->DispatchMouseButtonEvent(MouseButtonEventParams(
228 input_device_
.id
, cursor_
->GetLocation(), code
, down
,
229 /* allow_remap */ true, timestamp
));
232 void EventConverterEvdevImpl::FlushEvents(const input_event
& input
) {
233 if (!cursor_
|| (x_offset_
== 0 && y_offset_
== 0))
236 cursor_
->MoveCursor(gfx::Vector2dF(x_offset_
, y_offset_
));
238 dispatcher_
->DispatchMouseMoveEvent(
239 MouseMoveEventParams(input_device_
.id
, cursor_
->GetLocation(),
240 TimeDeltaFromInputEvent(input
)));