Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / ui / events / ozone / evdev / keyboard_evdev.cc
blob1d4a5af8ac6d79411a7a1df4c9b212959e390091
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"
19 namespace ui {
21 namespace {
23 const int kRepeatDelayMs = 500;
24 const int kRepeatIntervalMs = 50;
26 int EventFlagToEvdevModifier(int flag) {
27 switch (flag) {
28 case EF_CAPS_LOCK_DOWN:
29 return EVDEV_MODIFIER_CAPS_LOCK;
30 case EF_SHIFT_DOWN:
31 return EVDEV_MODIFIER_SHIFT;
32 case EF_CONTROL_DOWN:
33 return EVDEV_MODIFIER_CONTROL;
34 case EF_ALT_DOWN:
35 return EVDEV_MODIFIER_ALT;
36 case EF_ALTGR_DOWN:
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;
48 case EF_COMMAND_DOWN:
49 return EVDEV_MODIFIER_COMMAND;
50 default:
51 return EVDEV_MODIFIER_NONE;
55 } // namespace
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),
65 repeat_sequence_(0),
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,
75 bool down,
76 base::TimeDelta timestamp) {
77 if (key > KEY_MAX)
78 return;
80 if (down == key_state_.test(key))
81 return;
83 // State transition: !(down) -> (down)
84 if (down)
85 key_state_.set(key);
86 else
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)
123 return;
125 int modifier = EventFlagToEvdevModifier(modifier_flag);
126 if (modifier == EVDEV_MODIFIER_NONE)
127 return;
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);
138 else
139 modifiers_->UpdateModifier(modifier, down);
142 void KeyboardEvdev::UpdateKeyRepeat(unsigned int key, bool down) {
143 if (!repeat_enabled_)
144 StopKeyRepeat();
145 else if (key != repeat_key_ && down)
146 StartKeyRepeat(key);
147 else if (key == repeat_key_ && !down)
148 StopKeyRepeat();
151 void KeyboardEvdev::StartKeyRepeat(unsigned int key) {
152 repeat_key_ = key;
153 repeat_sequence_++;
155 ScheduleKeyRepeat(repeat_delay_);
158 void KeyboardEvdev::StopKeyRepeat() {
159 repeat_key_ = KEY_RESERVED;
160 repeat_sequence_++;
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_),
167 delay);
170 void KeyboardEvdev::OnRepeatTimeout(unsigned int sequence) {
171 if (repeat_sequence_ != sequence)
172 return;
174 DispatchKey(repeat_key_, true /* down */, true /* repeat */,
175 EventTimeForNow());
177 ScheduleKeyRepeat(repeat_interval_);
180 void KeyboardEvdev::DispatchKey(unsigned int key,
181 bool down,
182 bool repeat,
183 base::TimeDelta timestamp) {
184 DomCode dom_code =
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))
189 return;
190 int flags = modifiers_->GetModifierFlags();
191 DomKey dom_key;
192 KeyboardCode key_code;
193 uint16 character;
194 uint32 platform_keycode = 0;
195 if (!keyboard_layout_engine_->Lookup(dom_code, flags, &dom_key, &character,
196 &key_code, &platform_keycode)) {
197 return;
199 if (!repeat)
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);
209 } // namespace ui