1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "composer/key_event_util.h"
31
32 #include <cctype>
33
34 #include "base/logging.h"
35 #include "base/port.h"
36 #include "protocol/commands.pb.h"
37
38 namespace mozc {
39 using commands::KeyEvent;
40
41 namespace {
42 const uint32 kAltMask =
43 KeyEvent::ALT | KeyEvent::LEFT_ALT | KeyEvent::RIGHT_ALT;
44 const uint32 kCtrlMask =
45 KeyEvent::CTRL | KeyEvent::LEFT_CTRL | KeyEvent::RIGHT_CTRL;
46 const uint32 kShiftMask =
47 KeyEvent::SHIFT | KeyEvent::LEFT_SHIFT | KeyEvent::RIGHT_SHIFT;
48 const uint32 kCapsMask = KeyEvent::CAPS;
49
Ignore(uint32 modifiers,uint32 modifiers_to_be_ignored)50 uint32 Ignore(uint32 modifiers, uint32 modifiers_to_be_ignored) {
51 return modifiers & ~modifiers_to_be_ignored;
52 }
53
Any(uint32 modifiers_to_be_tested,uint32 modifiers_to_be_queried)54 bool Any(uint32 modifiers_to_be_tested, uint32 modifiers_to_be_queried) {
55 return (modifiers_to_be_tested & modifiers_to_be_queried) != 0;
56 }
57
None(uint32 modifiers_to_be_tested,uint32 modifiers_to_be_queried)58 bool None(uint32 modifiers_to_be_tested, uint32 modifiers_to_be_queried) {
59 return !Any(modifiers_to_be_tested, modifiers_to_be_queried);
60 }
61
62 } // namespace
63
GetModifiers(const KeyEvent & key_event)64 uint32 KeyEventUtil::GetModifiers(const KeyEvent &key_event) {
65 uint32 modifiers = 0;
66 if (key_event.has_modifiers()) {
67 modifiers = key_event.modifiers();
68 } else {
69 for (size_t i = 0; i < key_event.modifier_keys_size(); ++i) {
70 modifiers |= key_event.modifier_keys(i);
71 }
72 }
73 return modifiers;
74 }
75
GetKeyInformation(const KeyEvent & key_event,KeyInformation * key)76 bool KeyEventUtil::GetKeyInformation(const KeyEvent &key_event,
77 KeyInformation *key) {
78 DCHECK(key);
79
80 const uint16 modifier_keys = static_cast<uint16>(GetModifiers(key_event));
81 const uint16 special_key = key_event.has_special_key() ?
82 key_event.special_key() : KeyEvent::NO_SPECIALKEY;
83 const uint32 key_code = key_event.has_key_code() ? key_event.key_code() : 0;
84
85 // Make sure the translation from the obsolete spesification.
86 // key_code should no longer contain control characters.
87 if (0 < key_code && key_code <= 32) {
88 return false;
89 }
90
91 *key =
92 (static_cast<KeyInformation>(modifier_keys) << 48) |
93 (static_cast<KeyInformation>(special_key) << 32) |
94 (static_cast<KeyInformation>(key_code));
95
96 return true;
97 }
98
NormalizeModifiers(const KeyEvent & key_event,KeyEvent * new_key_event)99 void KeyEventUtil::NormalizeModifiers(const KeyEvent &key_event,
100 KeyEvent *new_key_event) {
101 DCHECK(new_key_event);
102
103 // CTRL (or ALT, SHIFT) should be set on modifier_keys when
104 // LEFT (or RIGHT) ctrl is set.
105 // LEFT_CTRL (or others) is not handled on Japanese, so we remove these.
106 const uint32 kIgnorableModifierMask =
107 (KeyEvent::CAPS |
108 KeyEvent::LEFT_ALT | KeyEvent::RIGHT_ALT |
109 KeyEvent::LEFT_CTRL | KeyEvent::RIGHT_CTRL |
110 KeyEvent::LEFT_SHIFT | KeyEvent::RIGHT_SHIFT);
111
112 RemoveModifiers(key_event, kIgnorableModifierMask, new_key_event);
113
114 // Reverts the flip of alphabetical key events caused by CapsLock.
115 const uint32 original_modifiers = GetModifiers(key_event);
116 if ((original_modifiers & KeyEvent::CAPS) &&
117 key_event.has_key_code()) {
118 const uint32 key_code = key_event.key_code();
119 if ('A' <= key_code && key_code <= 'Z') {
120 new_key_event->set_key_code(key_code + ('a' - 'A'));
121 } else if ('a' <= key_code && key_code <= 'z') {
122 new_key_event->set_key_code(key_code + ('A' - 'a'));
123 }
124 }
125 }
126
NormalizeNumpadKey(const KeyEvent & key_event,KeyEvent * new_key_event)127 void KeyEventUtil::NormalizeNumpadKey(const KeyEvent &key_event,
128 KeyEvent *new_key_event) {
129 DCHECK(new_key_event);
130 new_key_event->CopyFrom(key_event);
131
132 if (!IsNumpadKey(*new_key_event)) {
133 return;
134 }
135 const KeyEvent::SpecialKey numpad_key = new_key_event->special_key();
136
137 // KeyEvent::SEPARATOR is transformed to Enter.
138 if (numpad_key == KeyEvent::SEPARATOR) {
139 new_key_event->set_special_key(KeyEvent::ENTER);
140 return;
141 }
142
143 new_key_event->clear_special_key();
144
145 // Handles number keys
146 if (KeyEvent::NUMPAD0 <= numpad_key && numpad_key <= KeyEvent::NUMPAD9) {
147 new_key_event->set_key_code(
148 static_cast<uint32>('0' + (numpad_key - KeyEvent::NUMPAD0)));
149 return;
150 }
151
152 char new_key_code;
153 switch (numpad_key) {
154 case KeyEvent::MULTIPLY:
155 new_key_code = '*';
156 break;
157 case KeyEvent::ADD:
158 new_key_code = '+';
159 break;
160 case KeyEvent::SUBTRACT:
161 new_key_code = '-';
162 break;
163 case KeyEvent::DECIMAL:
164 new_key_code = '.';
165 break;
166 case KeyEvent::DIVIDE:
167 new_key_code = '/';
168 break;
169 case KeyEvent::EQUALS:
170 new_key_code = '=';
171 break;
172 case KeyEvent::COMMA:
173 new_key_code = ',';
174 break;
175 default:
176 LOG(ERROR) << "Should not reach here.";
177 return;
178 }
179
180 new_key_event->set_key_code(static_cast<uint32>(new_key_code));
181 }
182
RemoveModifiers(const KeyEvent & key_event,uint32 remove_modifiers,KeyEvent * new_key_event)183 void KeyEventUtil::RemoveModifiers(const KeyEvent &key_event,
184 uint32 remove_modifiers,
185 KeyEvent *new_key_event) {
186 DCHECK(new_key_event);
187 new_key_event->CopyFrom(key_event);
188
189 if (HasAlt(remove_modifiers)) {
190 remove_modifiers |= KeyEvent::LEFT_ALT | KeyEvent::RIGHT_ALT;
191 }
192 if (HasCtrl(remove_modifiers)) {
193 remove_modifiers |= KeyEvent::LEFT_CTRL | KeyEvent::RIGHT_CTRL;
194 }
195 if (HasShift(remove_modifiers)) {
196 remove_modifiers |= KeyEvent::LEFT_SHIFT | KeyEvent::RIGHT_SHIFT;
197 }
198
199 new_key_event->clear_modifier_keys();
200 for (size_t i = 0; i < key_event.modifier_keys_size(); ++i) {
201 const KeyEvent::ModifierKey mod_key = key_event.modifier_keys(i);
202 if (!(remove_modifiers & mod_key)) {
203 new_key_event->add_modifier_keys(mod_key);
204 }
205 }
206 }
207
MaybeGetKeyStub(const KeyEvent & key_event,KeyInformation * key)208 bool KeyEventUtil::MaybeGetKeyStub(const KeyEvent &key_event,
209 KeyInformation *key) {
210 DCHECK(key);
211
212 // If any modifier keys were pressed, this function does nothing.
213 if (KeyEventUtil::GetModifiers(key_event) != 0) {
214 return false;
215 }
216
217 // No stub rule is supported for special keys yet.
218 if (key_event.has_special_key()) {
219 return false;
220 }
221
222 // Check if both key_code and key_string are invalid.
223 if ((!key_event.has_key_code() || key_event.key_code() <= 32) &&
224 (!key_event.has_key_string() || key_event.key_string().empty())) {
225 return false;
226 }
227
228 KeyEvent stub_key_event;
229 stub_key_event.set_special_key(KeyEvent::TEXT_INPUT);
230 if (!GetKeyInformation(stub_key_event, key)) {
231 return false;
232 }
233
234 return true;
235 }
236
HasAlt(uint32 modifiers)237 bool KeyEventUtil::HasAlt(uint32 modifiers) {
238 return Any(modifiers, kAltMask);
239 }
240
HasCtrl(uint32 modifiers)241 bool KeyEventUtil::HasCtrl(uint32 modifiers) {
242 return Any(modifiers, kCtrlMask);
243 }
244
HasShift(uint32 modifiers)245 bool KeyEventUtil::HasShift(uint32 modifiers) {
246 return Any(modifiers, kShiftMask);
247 }
248
HasCaps(uint32 modifiers)249 bool KeyEventUtil::HasCaps(uint32 modifiers) {
250 return Any(modifiers, kCapsMask);
251 }
252
IsAlt(uint32 modifiers)253 bool KeyEventUtil::IsAlt(uint32 modifiers) {
254 if (!HasAlt(modifiers)) {
255 return false;
256 }
257 return None(Ignore(modifiers, kCapsMask), ~kAltMask);
258 }
259
IsCtrl(uint32 modifiers)260 bool KeyEventUtil::IsCtrl(uint32 modifiers) {
261 if (!HasCtrl(modifiers)) {
262 return false;
263 }
264 return None(Ignore(modifiers, kCapsMask), ~kCtrlMask);
265 }
266
IsShift(uint32 modifiers)267 bool KeyEventUtil::IsShift(uint32 modifiers) {
268 if (!HasShift(modifiers)) {
269 return false;
270 }
271 return None(Ignore(modifiers, kCapsMask), ~kShiftMask);
272 }
273
IsAltCtrl(uint32 modifiers)274 bool KeyEventUtil::IsAltCtrl(uint32 modifiers) {
275 if (!HasAlt(modifiers) || !HasCtrl(modifiers)) {
276 return false;
277 }
278 return None(Ignore(modifiers, kCapsMask), ~(kAltMask | kCtrlMask));
279 }
280
IsAltShift(uint32 modifiers)281 bool KeyEventUtil::IsAltShift(uint32 modifiers) {
282 if (!HasAlt(modifiers) || !HasShift(modifiers)) {
283 return false;
284 }
285 return None(Ignore(modifiers, kCapsMask), ~(kAltMask | kShiftMask));
286 }
287
IsCtrlShift(uint32 modifiers)288 bool KeyEventUtil::IsCtrlShift(uint32 modifiers) {
289 if (!HasCtrl(modifiers) || !HasShift(modifiers)) {
290 return false;
291 }
292 return None(Ignore(modifiers, kCapsMask), ~(kCtrlMask | kShiftMask));
293 }
294
IsAltCtrlShift(uint32 modifiers)295 bool KeyEventUtil::IsAltCtrlShift(uint32 modifiers) {
296 if (!HasAlt(modifiers) || !HasCtrl(modifiers) || !HasShift(modifiers)) {
297 return false;
298 }
299 const auto kAltCtrlShiftMask = kAltMask | kCtrlMask | kShiftMask;
300 return None(Ignore(modifiers, kCapsMask), ~kAltCtrlShiftMask);
301 }
302
IsLowerAlphabet(const KeyEvent & key_event)303 bool KeyEventUtil::IsLowerAlphabet(const KeyEvent &key_event) {
304 if (!key_event.has_key_code()) {
305 return false;
306 }
307
308 const uint32 key_code = key_event.key_code();
309 const uint32 modifier_keys = GetModifiers(key_event);
310 const bool change_case = (HasShift(modifier_keys) != HasCaps(modifier_keys));
311
312 if (change_case) {
313 return isupper(key_code) != 0;
314 } else {
315 return islower(key_code) != 0;
316 }
317 }
318
IsUpperAlphabet(const KeyEvent & key_event)319 bool KeyEventUtil::IsUpperAlphabet(const KeyEvent &key_event) {
320 if (!key_event.has_key_code()) {
321 return false;
322 }
323
324 const uint32 key_code = key_event.key_code();
325 const uint32 modifier_keys = GetModifiers(key_event);
326 const bool change_case = (HasShift(modifier_keys) != HasCaps(modifier_keys));
327
328 if (change_case) {
329 return islower(key_code) != 0;
330 } else {
331 return isupper(key_code) != 0;
332 }
333 }
334
IsNumpadKey(const KeyEvent & key_event)335 bool KeyEventUtil::IsNumpadKey(const KeyEvent &key_event) {
336 if (!key_event.has_special_key()) {
337 return false;
338 }
339
340 const KeyEvent::SpecialKey special_key = key_event.special_key();
341 if (KeyEvent::NUMPAD0 <= special_key && special_key <= KeyEvent::EQUALS) {
342 return true;
343 }
344 if (special_key == KeyEvent::COMMA) {
345 return true;
346 }
347 return false;
348 }
349
350 } // namespace mozc
351