ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / ui / events / ozone / evdev / keyboard_evdev.cc
blobf28da45e2617a30ad17b6dac496a8367b5e0d9ef
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 "ui/events/event.h"
8 #include "ui/events/event_constants.h"
9 #include "ui/events/event_utils.h"
10 #include "ui/events/keycodes/dom4/keycode_converter.h"
11 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
12 #include "ui/events/ozone/evdev/keyboard_util_evdev.h"
13 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
14 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
15 #include "ui/events/ozone/layout/layout_util.h"
17 namespace ui {
19 namespace {
21 const int kRepeatDelayMs = 500;
22 const int kRepeatIntervalMs = 50;
24 int EventFlagToEvdevModifier(int flag) {
25 switch (flag) {
26 case EF_CAPS_LOCK_DOWN:
27 return EVDEV_MODIFIER_CAPS_LOCK;
28 case EF_SHIFT_DOWN:
29 return EVDEV_MODIFIER_SHIFT;
30 case EF_CONTROL_DOWN:
31 return EVDEV_MODIFIER_CONTROL;
32 case EF_ALT_DOWN:
33 return EVDEV_MODIFIER_ALT;
34 case EF_ALTGR_DOWN:
35 return EVDEV_MODIFIER_ALTGR;
36 case EF_LEFT_MOUSE_BUTTON:
37 return EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
38 case EF_MIDDLE_MOUSE_BUTTON:
39 return EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
40 case EF_RIGHT_MOUSE_BUTTON:
41 return EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
42 case EF_COMMAND_DOWN:
43 return EVDEV_MODIFIER_COMMAND;
44 default:
45 return EVDEV_MODIFIER_NONE;
49 } // namespace
51 KeyboardEvdev::KeyboardEvdev(EventModifiersEvdev* modifiers,
52 KeyboardLayoutEngine* keyboard_layout_engine,
53 const EventDispatchCallback& callback)
54 : callback_(callback),
55 modifiers_(modifiers),
56 keyboard_layout_engine_(keyboard_layout_engine),
57 repeat_enabled_(true),
58 repeat_key_(KEY_RESERVED) {
59 repeat_delay_ = base::TimeDelta::FromMilliseconds(kRepeatDelayMs);
60 repeat_interval_ = base::TimeDelta::FromMilliseconds(kRepeatIntervalMs);
63 KeyboardEvdev::~KeyboardEvdev() {
66 void KeyboardEvdev::OnKeyChange(unsigned int key,
67 bool down,
68 base::TimeDelta timestamp) {
69 if (key > KEY_MAX)
70 return;
72 if (down == key_state_.test(key))
73 return;
75 // State transition: !(down) -> (down)
76 if (down)
77 key_state_.set(key);
78 else
79 key_state_.reset(key);
81 UpdateKeyRepeat(key, down);
82 DispatchKey(key, down, false /* repeat */, timestamp);
85 void KeyboardEvdev::Reset() {
86 for (int key = 0; key < KEY_CNT; ++key)
87 OnKeyChange(key, false /* down */, ui::EventTimeForNow());
90 void KeyboardEvdev::SetCapsLockEnabled(bool enabled) {
91 modifiers_->SetModifierLock(EVDEV_MODIFIER_CAPS_LOCK, enabled);
94 bool KeyboardEvdev::IsCapsLockEnabled() {
95 return (modifiers_->GetModifierFlags() & EF_CAPS_LOCK_DOWN) != 0;
98 bool KeyboardEvdev::IsAutoRepeatEnabled() {
99 return repeat_enabled_;
102 void KeyboardEvdev::SetAutoRepeatEnabled(bool enabled) {
103 repeat_enabled_ = enabled;
106 void KeyboardEvdev::SetAutoRepeatRate(const base::TimeDelta& delay,
107 const base::TimeDelta& interval) {
108 repeat_delay_ = delay;
109 repeat_interval_ = interval;
112 void KeyboardEvdev::GetAutoRepeatRate(base::TimeDelta* delay,
113 base::TimeDelta* interval) {
114 *delay = repeat_delay_;
115 *interval = repeat_interval_;
118 void KeyboardEvdev::UpdateModifier(int modifier_flag, bool down) {
119 if (modifier_flag == EF_NONE)
120 return;
122 int modifier = EventFlagToEvdevModifier(modifier_flag);
123 if (modifier == EVDEV_MODIFIER_NONE)
124 return;
126 // TODO post-X11: Revise remapping to not use EF_MOD3_DOWN.
127 // Currently EF_MOD3_DOWN means that the CapsLock key is currently down,
128 // and EF_CAPS_LOCK_DOWN means the caps lock state is enabled (and the
129 // key may or may not be down, but usually isn't). There does need to
130 // to be two different flags, since the physical CapsLock key is subject
131 // to remapping, but the caps lock state (which can be triggered in a
132 // variety of ways) is not.
133 if (modifier == EVDEV_MODIFIER_CAPS_LOCK)
134 modifiers_->UpdateModifier(EVDEV_MODIFIER_MOD3, down);
135 else
136 modifiers_->UpdateModifier(modifier, down);
139 void KeyboardEvdev::UpdateKeyRepeat(unsigned int key, bool down) {
140 if (!repeat_enabled_)
141 StopKeyRepeat();
142 else if (key != repeat_key_ && down)
143 StartKeyRepeat(key);
144 else if (key == repeat_key_ && !down)
145 StopKeyRepeat();
148 void KeyboardEvdev::StartKeyRepeat(unsigned int key) {
149 repeat_key_ = key;
150 repeat_delay_timer_.Start(
151 FROM_HERE, repeat_delay_,
152 base::Bind(&KeyboardEvdev::OnRepeatDelayTimeout, base::Unretained(this)));
153 repeat_interval_timer_.Stop();
156 void KeyboardEvdev::StopKeyRepeat() {
157 repeat_key_ = KEY_RESERVED;
158 repeat_delay_timer_.Stop();
159 repeat_interval_timer_.Stop();
162 void KeyboardEvdev::OnRepeatDelayTimeout() {
163 DispatchKey(repeat_key_, true /* down */, true /* repeat */,
164 EventTimeForNow());
166 repeat_interval_timer_.Start(
167 FROM_HERE, repeat_interval_,
168 base::Bind(&KeyboardEvdev::OnRepeatIntervalTimeout,
169 base::Unretained(this)));
172 void KeyboardEvdev::OnRepeatIntervalTimeout() {
173 DispatchKey(repeat_key_, true /* down */, true /* repeat */,
174 EventTimeForNow());
177 void KeyboardEvdev::DispatchKey(unsigned int key,
178 bool down,
179 bool repeat,
180 base::TimeDelta timestamp) {
181 DomCode dom_code =
182 KeycodeConverter::NativeKeycodeToDomCode(EvdevCodeToNativeCode(key));
183 // DomCode constants are not included here because of conflicts with
184 // evdev preprocessor macros.
185 if (!static_cast<int>(dom_code))
186 return;
187 int flags = modifiers_->GetModifierFlags();
188 DomKey dom_key;
189 KeyboardCode key_code;
190 uint16 character;
191 uint32 platform_keycode = 0;
192 if (!keyboard_layout_engine_->Lookup(dom_code, flags, &dom_key, &character,
193 &key_code, &platform_keycode)) {
194 return;
196 if (!repeat)
197 UpdateModifier(ModifierDomKeyToEventFlag(dom_key), down);
199 KeyEvent event(down ? ET_KEY_PRESSED : ET_KEY_RELEASED, key_code, dom_code,
200 modifiers_->GetModifierFlags(), dom_key, character, timestamp);
201 if (platform_keycode)
202 event.set_platform_keycode(platform_keycode);
203 callback_.Run(&event);
206 } // namespace ui