OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/input_method/xkeyboard.h" | 5 #include "chrome/browser/chromeos/input_method/xkeyboard.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <set> | 8 #include <set> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 "xkb:us:altgr-intl:eng", | 89 "xkb:us:altgr-intl:eng", |
90 "xkb:us:intl:eng", | 90 "xkb:us:intl:eng", |
91 }; | 91 }; |
92 | 92 |
93 // These are the overlay names with caps lock remapped | 93 // These are the overlay names with caps lock remapped |
94 const char* kCapsLockRemapped[] = { | 94 const char* kCapsLockRemapped[] = { |
95 "xkb:de:neo:ger", | 95 "xkb:de:neo:ger", |
96 "xkb:us:colemak:eng", | 96 "xkb:us:colemak:eng", |
97 }; | 97 }; |
98 | 98 |
99 // A string for obtaining a mask value for Num Lock. | |
100 const char kNumLockVirtualModifierString[] = "NumLock"; | |
101 | |
99 } // namespace | 102 } // namespace |
100 | 103 |
101 XKeyboard::XKeyboard(const InputMethodUtil& util) | 104 XKeyboard::XKeyboard(const InputMethodUtil& util) |
102 : is_running_on_chrome_os_( | 105 : is_running_on_chrome_os_( |
103 system::runtime_environment::IsRunningOnChromeOS()) { | 106 system::runtime_environment::IsRunningOnChromeOS()) { |
107 num_lock_mask_ = GetNumLockMask(); | |
108 current_num_lock_status_ = NumLockIsEnabled(num_lock_mask_); | |
109 current_caps_lock_status_ = CapsLockIsEnabled(); | |
110 | |
104 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) { | 111 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) { |
105 ModifierKey key = kCustomizableKeys[i]; | 112 ModifierKey key = kCustomizableKeys[i]; |
106 current_modifier_map_.push_back(ModifierKeyPair(key, key)); | 113 current_modifier_map_.push_back(ModifierKeyPair(key, key)); |
107 } | 114 } |
115 | |
108 std::string layout; | 116 std::string layout; |
109 for (size_t i = 0; i < arraysize(kKeepRightAltInputMethods); ++i) { | 117 for (size_t i = 0; i < arraysize(kKeepRightAltInputMethods); ++i) { |
110 layout = util.GetKeyboardLayoutName(kKeepRightAltInputMethods[i]); | 118 layout = util.GetKeyboardLayoutName(kKeepRightAltInputMethods[i]); |
111 // The empty check is necessary since TOUCH_UI build does not support some | 119 // The empty check is necessary since TOUCH_UI build does not support some |
112 // of the kKeepRightAltInputMethods elements. For example, when TOUCH_UI is | 120 // of the kKeepRightAltInputMethods elements. For example, when TOUCH_UI is |
113 // defined, util.GetKeyboardLayoutName("xkb:us:intl:eng") would return "". | 121 // defined, util.GetKeyboardLayoutName("xkb:us:intl:eng") would return "". |
114 if (!layout.empty()) { | 122 if (!layout.empty()) { |
115 keep_right_alt_xkb_layout_names_.insert(layout); | 123 keep_right_alt_xkb_layout_names_.insert(layout); |
116 } | 124 } |
117 } | 125 } |
118 for (size_t i = 0; i < arraysize(kCapsLockRemapped); ++i) { | 126 for (size_t i = 0; i < arraysize(kCapsLockRemapped); ++i) { |
119 layout = util.GetKeyboardLayoutName(kCapsLockRemapped[i]); | 127 layout = util.GetKeyboardLayoutName(kCapsLockRemapped[i]); |
120 // The empty check is for TOUCH_UI build. See above. | 128 // The empty check is for TOUCH_UI build. See above. |
121 if (!layout.empty()) { | 129 if (!layout.empty()) { |
122 caps_lock_remapped_xkb_layout_names_.insert(layout); | 130 caps_lock_remapped_xkb_layout_names_.insert(layout); |
123 } | 131 } |
124 } | 132 } |
125 } | 133 } |
126 | 134 |
127 XKeyboard::~XKeyboard() { | 135 XKeyboard::~XKeyboard() { |
128 } | 136 } |
129 | 137 |
138 // static | |
139 unsigned int XKeyboard::GetNumLockMask() { | |
140 static const unsigned int kBadMask = 0; | |
141 | |
142 unsigned int real_mask = kBadMask; | |
143 XkbDescPtr xkb_desc = | |
144 XkbGetKeyboard(ui::GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd); | |
145 if (!xkb_desc) { | |
146 return kBadMask; | |
147 } | |
148 | |
149 if (xkb_desc->dpy && xkb_desc->names && xkb_desc->names->vmods) { | |
150 const std::string string_to_find(kNumLockVirtualModifierString); | |
151 for (size_t i = 0; i < XkbNumVirtualMods; ++i) { | |
152 const unsigned int virtual_mod_mask = 1U << i; | |
153 const char* virtual_mod_str = | |
154 XGetAtomName(xkb_desc->dpy, xkb_desc->names->vmods[i]); | |
155 if (!virtual_mod_str) { | |
156 continue; | |
157 } | |
158 if (string_to_find == virtual_mod_str) { | |
159 if (!XkbVirtualModsToReal(xkb_desc, virtual_mod_mask, &real_mask)) { | |
160 LOG(ERROR) << "XkbVirtualModsToReal failed"; | |
161 real_mask = kBadMask; // reset the return value, just in case. | |
162 } | |
163 break; | |
164 } | |
165 } | |
166 } | |
167 XkbFreeKeyboard(xkb_desc, 0, True /* free all components */); | |
168 | |
169 // Some code in Chrome, e.g. web_input_event_aurax11.cc, assume that Mod2Mask | |
170 // is always assigned to Num Lock. | |
171 // TODO(yusukes): Check the assumption is really okay. If not, modify such | |
172 // code, and then remove the CHECK below. | |
173 CHECK(real_mask == Mod2Mask); | |
174 | |
175 return real_mask; | |
176 } | |
177 | |
130 bool XKeyboard::SetLayoutInternal(const std::string& layout_name, | 178 bool XKeyboard::SetLayoutInternal(const std::string& layout_name, |
131 const ModifierMap& modifier_map, | 179 const ModifierMap& modifier_map, |
132 bool force) { | 180 bool force) { |
133 if (!is_running_on_chrome_os_) { | 181 if (!is_running_on_chrome_os_) { |
134 // We should not try to change a layout on Linux or inside ui_tests. Just | 182 // We should not try to change a layout on Linux or inside ui_tests. Just |
135 // return true. | 183 // return true. |
136 return true; | 184 return true; |
137 } | 185 } |
138 | 186 |
139 const std::string layout_to_set = CreateFullXkbLayoutName( | 187 const std::string layout_to_set = CreateFullXkbLayoutName( |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 } | 368 } |
321 | 369 |
322 // static | 370 // static |
323 bool XKeyboard::CapsLockIsEnabled() { | 371 bool XKeyboard::CapsLockIsEnabled() { |
324 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 372 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
325 XkbStateRec status; | 373 XkbStateRec status; |
326 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); | 374 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); |
327 return status.locked_mods & LockMask; | 375 return status.locked_mods & LockMask; |
328 } | 376 } |
329 | 377 |
330 // static | |
331 void XKeyboard::SetCapsLockEnabled(bool enable_caps_lock) { | 378 void XKeyboard::SetCapsLockEnabled(bool enable_caps_lock) { |
332 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 379 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
333 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, LockMask, | 380 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, LockMask, |
334 enable_caps_lock ? LockMask : 0); | 381 enable_caps_lock ? LockMask : 0); |
382 current_caps_lock_status_ = enable_caps_lock; | |
335 } | 383 } |
336 | 384 |
337 // static | 385 // static |
386 bool XKeyboard::NumLockIsEnabled(unsigned int num_lock_mask) { | |
387 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
388 if (!num_lock_mask) { | |
389 LOG(ERROR) << "Cannot get Num Lock status. Mask unknown."; | |
390 return true; | |
391 } | |
392 XkbStateRec status; | |
393 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); | |
394 return status.locked_mods & num_lock_mask; | |
395 } | |
396 | |
397 void XKeyboard::SetNumLockEnabled(bool enable_num_lock) { | |
398 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
399 if (!num_lock_mask_) { | |
400 LOG(ERROR) << "Cannot set Num Lock status. Mask unknown."; | |
401 return; | |
402 } | |
403 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, num_lock_mask_, | |
404 enable_num_lock ? num_lock_mask_ : 0); | |
405 current_num_lock_status_ = enable_num_lock; | |
406 } | |
407 | |
408 // static | |
338 bool XKeyboard::ContainsModifierKeyAsReplacement( | 409 bool XKeyboard::ContainsModifierKeyAsReplacement( |
339 const ModifierMap& modifier_map, ModifierKey key) { | 410 const ModifierMap& modifier_map, ModifierKey key) { |
340 for (size_t i = 0; i < modifier_map.size(); ++i) { | 411 for (size_t i = 0; i < modifier_map.size(); ++i) { |
341 if (modifier_map[i].replacement == key) { | 412 if (modifier_map[i].replacement == key) { |
342 return true; | 413 return true; |
343 } | 414 } |
344 } | 415 } |
345 return false; | 416 return false; |
346 } | 417 } |
347 | 418 |
348 bool XKeyboard::SetCurrentKeyboardLayoutByName(const std::string& layout_name) { | 419 bool XKeyboard::SetCurrentKeyboardLayoutByName(const std::string& layout_name) { |
349 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) { | 420 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) { |
350 current_layout_name_ = layout_name; | 421 current_layout_name_ = layout_name; |
351 return true; | 422 return true; |
352 } | 423 } |
353 return false; | 424 return false; |
354 } | 425 } |
355 | 426 |
356 bool XKeyboard::ReapplyCurrentKeyboardLayout() { | 427 bool XKeyboard::ReapplyCurrentKeyboardLayout() { |
357 if (current_layout_name_.empty()) { | 428 if (current_layout_name_.empty()) { |
358 LOG(ERROR) << "Can't reapply XKB layout: layout unknown"; | 429 LOG(ERROR) << "Can't reapply XKB layout: layout unknown"; |
359 return false; | 430 return false; |
360 } | 431 } |
361 return SetLayoutInternal( | 432 return SetLayoutInternal( |
362 current_layout_name_, current_modifier_map_, true /* force */); | 433 current_layout_name_, current_modifier_map_, true /* force */); |
363 } | 434 } |
364 | 435 |
436 void XKeyboard::ReapplyCurrentModifierLockStatus() { | |
437 SetCapsLockEnabled(current_caps_lock_status_); | |
Daniel Kurtz
2011/11/04 11:49:18
Save yourself a round trip to the server by applyi
Yusuke Sato
2011/11/07 04:31:28
Done.
| |
438 SetNumLockEnabled(current_num_lock_status_); | |
439 } | |
440 | |
365 bool XKeyboard::RemapModifierKeys(const ModifierMap& modifier_map) { | 441 bool XKeyboard::RemapModifierKeys(const ModifierMap& modifier_map) { |
366 const std::string layout_name = current_layout_name_.empty() ? | 442 const std::string layout_name = current_layout_name_.empty() ? |
367 kDefaultLayoutName : current_layout_name_; | 443 kDefaultLayoutName : current_layout_name_; |
368 if (SetLayoutInternal(layout_name, modifier_map, false)) { | 444 if (SetLayoutInternal(layout_name, modifier_map, false)) { |
369 current_layout_name_ = layout_name; | 445 current_layout_name_ = layout_name; |
370 current_modifier_map_ = modifier_map; | 446 current_modifier_map_ = modifier_map; |
371 return true; | 447 return true; |
372 } | 448 } |
373 return false; | 449 return false; |
374 } | 450 } |
(...skipping 20 matching lines...) Expand all Loading... | |
395 case kCapsLockKey: | 471 case kCapsLockKey: |
396 return "capslock"; | 472 return "capslock"; |
397 case kNumModifierKeys: | 473 case kNumModifierKeys: |
398 break; | 474 break; |
399 } | 475 } |
400 return ""; | 476 return ""; |
401 } | 477 } |
402 | 478 |
403 } // namespace input_method | 479 } // namespace input_method |
404 } // namespace chromeos | 480 } // namespace chromeos |
OLD | NEW |