base: Change DCHECK_IS_ON to a macro DCHECK_IS_ON().
[chromium-blink-merge.git] / ui / events / ozone / evdev / keyboard_evdev.cc
blobde7d84ac997e63ea275da4d3f9aa56ce278502f8
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/keycodes/dom4/keycode_converter.h"
10 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
11 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
12 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
13 #include "ui/events/ozone/layout/layout_util.h"
15 namespace ui {
17 namespace {
19 const int kXkbKeycodeOffset = 8;
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 bool IsModifierLock(int evdev_modifier) {
50 return evdev_modifier == EVDEV_MODIFIER_CAPS_LOCK;
53 } // namespace
55 KeyboardEvdev::KeyboardEvdev(EventModifiersEvdev* modifiers,
56 KeyboardLayoutEngine* keyboard_layout_engine,
57 const EventDispatchCallback& callback)
58 : callback_(callback),
59 modifiers_(modifiers),
60 keyboard_layout_engine_(keyboard_layout_engine),
61 repeat_enabled_(true),
62 repeat_key_(KEY_RESERVED) {
63 repeat_delay_ = base::TimeDelta::FromMilliseconds(kRepeatDelayMs);
64 repeat_interval_ = base::TimeDelta::FromMilliseconds(kRepeatIntervalMs);
67 KeyboardEvdev::~KeyboardEvdev() {
70 void KeyboardEvdev::OnKeyChange(unsigned int key, bool down) {
71 if (key > KEY_MAX)
72 return;
74 if (down == key_state_.test(key))
75 return;
77 // State transition: !(down) -> (down)
78 if (down)
79 key_state_.set(key);
80 else
81 key_state_.reset(key);
83 UpdateKeyRepeat(key, down);
84 DispatchKey(key, down, false /* repeat */);
87 bool KeyboardEvdev::IsAutoRepeatEnabled() {
88 return repeat_enabled_;
91 void KeyboardEvdev::SetAutoRepeatEnabled(bool enabled) {
92 repeat_enabled_ = enabled;
95 void KeyboardEvdev::SetAutoRepeatRate(const base::TimeDelta& delay,
96 const base::TimeDelta& interval) {
97 repeat_delay_ = delay;
98 repeat_interval_ = interval;
101 void KeyboardEvdev::GetAutoRepeatRate(base::TimeDelta* delay,
102 base::TimeDelta* interval) {
103 *delay = repeat_delay_;
104 *interval = repeat_interval_;
107 void KeyboardEvdev::UpdateModifier(int modifier_flag, bool down) {
108 if (modifier_flag == EF_NONE)
109 return;
111 int modifier = EventFlagToEvdevModifier(modifier_flag);
112 if (modifier == EVDEV_MODIFIER_NONE)
113 return;
115 if (IsModifierLock(modifier))
116 modifiers_->UpdateModifierLock(modifier, down);
117 else
118 modifiers_->UpdateModifier(modifier, down);
121 void KeyboardEvdev::UpdateKeyRepeat(unsigned int key, bool down) {
122 if (!repeat_enabled_)
123 StopKeyRepeat();
124 else if (key != repeat_key_ && down)
125 StartKeyRepeat(key);
126 else if (key == repeat_key_ && !down)
127 StopKeyRepeat();
130 void KeyboardEvdev::StartKeyRepeat(unsigned int key) {
131 repeat_key_ = key;
132 repeat_delay_timer_.Start(
133 FROM_HERE, repeat_delay_,
134 base::Bind(&KeyboardEvdev::OnRepeatDelayTimeout, base::Unretained(this)));
135 repeat_interval_timer_.Stop();
138 void KeyboardEvdev::StopKeyRepeat() {
139 repeat_key_ = KEY_RESERVED;
140 repeat_delay_timer_.Stop();
141 repeat_interval_timer_.Stop();
144 void KeyboardEvdev::OnRepeatDelayTimeout() {
145 DispatchKey(repeat_key_, true /* down */, true /* repeat */);
147 repeat_interval_timer_.Start(
148 FROM_HERE, repeat_interval_,
149 base::Bind(&KeyboardEvdev::OnRepeatIntervalTimeout,
150 base::Unretained(this)));
153 void KeyboardEvdev::OnRepeatIntervalTimeout() {
154 DispatchKey(repeat_key_, true /* down */, true /* repeat */);
157 void KeyboardEvdev::DispatchKey(unsigned int key, bool down, bool repeat) {
158 DomCode dom_code =
159 KeycodeConverter::NativeKeycodeToDomCode(key + kXkbKeycodeOffset);
160 // DomCode constants are not included here because of conflicts with
161 // evdev preprocessor macros.
162 if (!static_cast<int>(dom_code))
163 return;
164 int flags = modifiers_->GetModifierFlags();
165 DomKey dom_key;
166 KeyboardCode key_code;
167 uint16 character;
168 uint32 platform_keycode = 0;
169 if (!keyboard_layout_engine_->Lookup(dom_code, flags, &dom_key, &character,
170 &key_code, &platform_keycode)) {
171 return;
173 if (!repeat)
174 UpdateModifier(ModifierDomKeyToEventFlag(dom_key), down);
176 KeyEvent* event =
177 new KeyEvent(down ? ET_KEY_PRESSED : ET_KEY_RELEASED, key_code, dom_code,
178 modifiers_->GetModifierFlags(), dom_key, character);
179 if (platform_keycode)
180 event->set_platform_keycode(platform_keycode);
181 callback_.Run(make_scoped_ptr(event));
184 // static
185 int KeyboardEvdev::NativeCodeToEvdevCode(int native_code) {
186 if (native_code == KeycodeConverter::InvalidNativeKeycode()) {
187 return KEY_RESERVED;
189 return native_code - kXkbKeycodeOffset;
192 } // namespace ui