Chromium Code Reviews| 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 |