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/keyboard_evdev.h"
7 #include "base/single_thread_task_runner.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "ui/events/event.h"
10 #include "ui/events/event_constants.h"
11 #include "ui/events/event_utils.h"
12 #include "ui/events/keycodes/dom4/keycode_converter.h"
13 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
14 #include "ui/events/ozone/evdev/keyboard_util_evdev.h"
15 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
16 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
17 #include "ui/events/ozone/layout/layout_util.h"
23 const int kRepeatDelayMs
= 500;
24 const int kRepeatIntervalMs
= 50;
26 int EventFlagToEvdevModifier(int flag
) {
28 case EF_CAPS_LOCK_DOWN
:
29 return EVDEV_MODIFIER_CAPS_LOCK
;
31 return EVDEV_MODIFIER_SHIFT
;
33 return EVDEV_MODIFIER_CONTROL
;
35 return EVDEV_MODIFIER_ALT
;
37 return EVDEV_MODIFIER_ALTGR
;
38 case EF_LEFT_MOUSE_BUTTON
:
39 return EVDEV_MODIFIER_LEFT_MOUSE_BUTTON
;
40 case EF_MIDDLE_MOUSE_BUTTON
:
41 return EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON
;
42 case EF_RIGHT_MOUSE_BUTTON
:
43 return EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON
;
44 case EF_BACK_MOUSE_BUTTON
:
45 return EVDEV_MODIFIER_BACK_MOUSE_BUTTON
;
46 case EF_FORWARD_MOUSE_BUTTON
:
47 return EVDEV_MODIFIER_FORWARD_MOUSE_BUTTON
;
49 return EVDEV_MODIFIER_COMMAND
;
51 return EVDEV_MODIFIER_NONE
;
57 KeyboardEvdev::KeyboardEvdev(EventModifiersEvdev
* modifiers
,
58 KeyboardLayoutEngine
* keyboard_layout_engine
,
59 const EventDispatchCallback
& callback
)
60 : callback_(callback
),
61 modifiers_(modifiers
),
62 keyboard_layout_engine_(keyboard_layout_engine
),
63 repeat_enabled_(true),
64 repeat_key_(KEY_RESERVED
),
66 weak_ptr_factory_(this) {
67 repeat_delay_
= base::TimeDelta::FromMilliseconds(kRepeatDelayMs
);
68 repeat_interval_
= base::TimeDelta::FromMilliseconds(kRepeatIntervalMs
);
71 KeyboardEvdev::~KeyboardEvdev() {
74 void KeyboardEvdev::OnKeyChange(unsigned int key
,
76 base::TimeDelta timestamp
) {
80 if (down
== key_state_
.test(key
))
83 // State transition: !(down) -> (down)
87 key_state_
.reset(key
);
89 UpdateKeyRepeat(key
, down
);
90 DispatchKey(key
, down
, false /* repeat */, timestamp
);
93 void KeyboardEvdev::SetCapsLockEnabled(bool enabled
) {
94 modifiers_
->SetModifierLock(EVDEV_MODIFIER_CAPS_LOCK
, enabled
);
97 bool KeyboardEvdev::IsCapsLockEnabled() {
98 return (modifiers_
->GetModifierFlags() & EF_CAPS_LOCK_DOWN
) != 0;
101 bool KeyboardEvdev::IsAutoRepeatEnabled() {
102 return repeat_enabled_
;
105 void KeyboardEvdev::SetAutoRepeatEnabled(bool enabled
) {
106 repeat_enabled_
= enabled
;
109 void KeyboardEvdev::SetAutoRepeatRate(const base::TimeDelta
& delay
,
110 const base::TimeDelta
& interval
) {
111 repeat_delay_
= delay
;
112 repeat_interval_
= interval
;
115 void KeyboardEvdev::GetAutoRepeatRate(base::TimeDelta
* delay
,
116 base::TimeDelta
* interval
) {
117 *delay
= repeat_delay_
;
118 *interval
= repeat_interval_
;
121 void KeyboardEvdev::UpdateModifier(int modifier_flag
, bool down
) {
122 if (modifier_flag
== EF_NONE
)
125 int modifier
= EventFlagToEvdevModifier(modifier_flag
);
126 if (modifier
== EVDEV_MODIFIER_NONE
)
129 // TODO post-X11: Revise remapping to not use EF_MOD3_DOWN.
130 // Currently EF_MOD3_DOWN means that the CapsLock key is currently down,
131 // and EF_CAPS_LOCK_DOWN means the caps lock state is enabled (and the
132 // key may or may not be down, but usually isn't). There does need to
133 // to be two different flags, since the physical CapsLock key is subject
134 // to remapping, but the caps lock state (which can be triggered in a
135 // variety of ways) is not.
136 if (modifier
== EVDEV_MODIFIER_CAPS_LOCK
)
137 modifiers_
->UpdateModifier(EVDEV_MODIFIER_MOD3
, down
);
139 modifiers_
->UpdateModifier(modifier
, down
);
142 void KeyboardEvdev::UpdateKeyRepeat(unsigned int key
, bool down
) {
143 if (!repeat_enabled_
)
145 else if (key
!= repeat_key_
&& down
)
147 else if (key
== repeat_key_
&& !down
)
151 void KeyboardEvdev::StartKeyRepeat(unsigned int key
) {
155 ScheduleKeyRepeat(repeat_delay_
);
158 void KeyboardEvdev::StopKeyRepeat() {
159 repeat_key_
= KEY_RESERVED
;
163 void KeyboardEvdev::ScheduleKeyRepeat(const base::TimeDelta
& delay
) {
164 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
165 FROM_HERE
, base::Bind(&KeyboardEvdev::OnRepeatTimeout
,
166 weak_ptr_factory_
.GetWeakPtr(), repeat_sequence_
),
170 void KeyboardEvdev::OnRepeatTimeout(unsigned int sequence
) {
171 if (repeat_sequence_
!= sequence
)
174 DispatchKey(repeat_key_
, true /* down */, true /* repeat */,
177 ScheduleKeyRepeat(repeat_interval_
);
180 void KeyboardEvdev::DispatchKey(unsigned int key
,
183 base::TimeDelta timestamp
) {
185 KeycodeConverter::NativeKeycodeToDomCode(EvdevCodeToNativeCode(key
));
186 // DomCode constants are not included here because of conflicts with
187 // evdev preprocessor macros.
188 if (!static_cast<int>(dom_code
))
190 int flags
= modifiers_
->GetModifierFlags();
192 KeyboardCode key_code
;
194 uint32 platform_keycode
= 0;
195 if (!keyboard_layout_engine_
->Lookup(dom_code
, flags
, &dom_key
, &character
,
196 &key_code
, &platform_keycode
)) {
200 UpdateModifier(ModifierDomKeyToEventFlag(dom_key
), down
);
202 KeyEvent
event(down
? ET_KEY_PRESSED
: ET_KEY_RELEASED
, key_code
, dom_code
,
203 modifiers_
->GetModifierFlags(), dom_key
, character
, timestamp
);
204 if (platform_keycode
)
205 event
.set_platform_keycode(platform_keycode
);
206 callback_
.Run(&event
);