| 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 GetLockedModifiers( |
| 109 num_lock_mask_, ¤t_caps_lock_status_, ¤t_num_lock_status_); |
| 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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 << rate.repeat_interval_in_ms << " ms interval"; | 360 << rate.repeat_interval_in_ms << " ms interval"; |
| 313 if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, | 361 if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, |
| 314 rate.initial_delay_in_ms, | 362 rate.initial_delay_in_ms, |
| 315 rate.repeat_interval_in_ms) != True) { | 363 rate.repeat_interval_in_ms) != True) { |
| 316 LOG(ERROR) << "Failed to set auto-repeat rate"; | 364 LOG(ERROR) << "Failed to set auto-repeat rate"; |
| 317 return false; | 365 return false; |
| 318 } | 366 } |
| 319 return true; | 367 return true; |
| 320 } | 368 } |
| 321 | 369 |
| 370 void XKeyboard::SetLockedModifiers(ModifierLockStatus new_caps_lock_status, |
| 371 ModifierLockStatus new_num_lock_status) { |
| 372 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 373 if (!num_lock_mask_) { |
| 374 LOG(ERROR) << "Cannot set locked modifiers. Num Lock mask unknown."; |
| 375 return; |
| 376 } |
| 377 |
| 378 unsigned int affect_mask = 0; |
| 379 unsigned int value_mask = 0; |
| 380 if (new_caps_lock_status != kDontChange) { |
| 381 affect_mask |= LockMask; |
| 382 value_mask |= ((new_caps_lock_status == kEnableLock) ? LockMask : 0); |
| 383 current_caps_lock_status_ = (new_caps_lock_status == kEnableLock); |
| 384 } |
| 385 if (new_num_lock_status != kDontChange) { |
| 386 affect_mask |= num_lock_mask_; |
| 387 value_mask |= ((new_num_lock_status == kEnableLock) ? num_lock_mask_ : 0); |
| 388 current_num_lock_status_ = (new_num_lock_status == kEnableLock); |
| 389 } |
| 390 |
| 391 if (affect_mask) { |
| 392 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, affect_mask, value_mask); |
| 393 } |
| 394 } |
| 395 |
| 396 void XKeyboard::SetNumLockEnabled(bool enable_num_lock) { |
| 397 SetLockedModifiers( |
| 398 kDontChange, enable_num_lock ? kEnableLock : kDisableLock); |
| 399 } |
| 400 |
| 401 void XKeyboard::SetCapsLockEnabled(bool enable_caps_lock) { |
| 402 SetLockedModifiers( |
| 403 enable_caps_lock ? kEnableLock : kDisableLock, kDontChange); |
| 404 } |
| 405 |
| 406 // static |
| 407 void XKeyboard::GetLockedModifiers(unsigned int num_lock_mask, |
| 408 bool* out_caps_lock_enabled, |
| 409 bool* out_num_lock_enabled) { |
| 410 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 411 |
| 412 if (out_num_lock_enabled && !num_lock_mask) { |
| 413 LOG(ERROR) << "Cannot get locked modifiers. Num Lock mask unknown."; |
| 414 if (out_caps_lock_enabled) { |
| 415 *out_caps_lock_enabled = false; |
| 416 } |
| 417 if (out_num_lock_enabled) { |
| 418 *out_num_lock_enabled = false; |
| 419 } |
| 420 return; |
| 421 } |
| 422 |
| 423 XkbStateRec status; |
| 424 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); |
| 425 if (out_caps_lock_enabled) { |
| 426 *out_caps_lock_enabled = status.locked_mods & LockMask; |
| 427 } |
| 428 if (out_num_lock_enabled) { |
| 429 *out_num_lock_enabled = status.locked_mods & num_lock_mask; |
| 430 } |
| 431 } |
| 432 |
| 433 // static |
| 434 bool XKeyboard::NumLockIsEnabled(unsigned int num_lock_mask) { |
| 435 bool num_lock_enabled = false; |
| 436 GetLockedModifiers(num_lock_mask, NULL /* Caps Lock */, &num_lock_enabled); |
| 437 return num_lock_enabled; |
| 438 } |
| 439 |
| 322 // static | 440 // static |
| 323 bool XKeyboard::CapsLockIsEnabled() { | 441 bool XKeyboard::CapsLockIsEnabled() { |
| 324 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 442 bool caps_lock_enabled = false; |
| 325 XkbStateRec status; | 443 GetLockedModifiers(0, &caps_lock_enabled, NULL /* Num Lock */); |
| 326 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); | 444 return caps_lock_enabled; |
| 327 return status.locked_mods & LockMask; | |
| 328 } | 445 } |
| 329 | 446 |
| 330 // static | 447 // static |
| 331 void XKeyboard::SetCapsLockEnabled(bool enable_caps_lock) { | |
| 332 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 333 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, LockMask, | |
| 334 enable_caps_lock ? LockMask : 0); | |
| 335 } | |
| 336 | |
| 337 // static | |
| 338 bool XKeyboard::ContainsModifierKeyAsReplacement( | 448 bool XKeyboard::ContainsModifierKeyAsReplacement( |
| 339 const ModifierMap& modifier_map, ModifierKey key) { | 449 const ModifierMap& modifier_map, ModifierKey key) { |
| 340 for (size_t i = 0; i < modifier_map.size(); ++i) { | 450 for (size_t i = 0; i < modifier_map.size(); ++i) { |
| 341 if (modifier_map[i].replacement == key) { | 451 if (modifier_map[i].replacement == key) { |
| 342 return true; | 452 return true; |
| 343 } | 453 } |
| 344 } | 454 } |
| 345 return false; | 455 return false; |
| 346 } | 456 } |
| 347 | 457 |
| 348 bool XKeyboard::SetCurrentKeyboardLayoutByName(const std::string& layout_name) { | 458 bool XKeyboard::SetCurrentKeyboardLayoutByName(const std::string& layout_name) { |
| 349 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) { | 459 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) { |
| 350 current_layout_name_ = layout_name; | 460 current_layout_name_ = layout_name; |
| 351 return true; | 461 return true; |
| 352 } | 462 } |
| 353 return false; | 463 return false; |
| 354 } | 464 } |
| 355 | 465 |
| 356 bool XKeyboard::ReapplyCurrentKeyboardLayout() { | 466 bool XKeyboard::ReapplyCurrentKeyboardLayout() { |
| 357 if (current_layout_name_.empty()) { | 467 if (current_layout_name_.empty()) { |
| 358 LOG(ERROR) << "Can't reapply XKB layout: layout unknown"; | 468 LOG(ERROR) << "Can't reapply XKB layout: layout unknown"; |
| 359 return false; | 469 return false; |
| 360 } | 470 } |
| 361 return SetLayoutInternal( | 471 return SetLayoutInternal( |
| 362 current_layout_name_, current_modifier_map_, true /* force */); | 472 current_layout_name_, current_modifier_map_, true /* force */); |
| 363 } | 473 } |
| 364 | 474 |
| 475 void XKeyboard::ReapplyCurrentModifierLockStatus() { |
| 476 SetLockedModifiers(current_caps_lock_status_ ? kEnableLock : kDisableLock, |
| 477 current_num_lock_status_ ? kEnableLock : kDisableLock); |
| 478 } |
| 479 |
| 365 bool XKeyboard::RemapModifierKeys(const ModifierMap& modifier_map) { | 480 bool XKeyboard::RemapModifierKeys(const ModifierMap& modifier_map) { |
| 366 const std::string layout_name = current_layout_name_.empty() ? | 481 const std::string layout_name = current_layout_name_.empty() ? |
| 367 kDefaultLayoutName : current_layout_name_; | 482 kDefaultLayoutName : current_layout_name_; |
| 368 if (SetLayoutInternal(layout_name, modifier_map, false)) { | 483 if (SetLayoutInternal(layout_name, modifier_map, false)) { |
| 369 current_layout_name_ = layout_name; | 484 current_layout_name_ = layout_name; |
| 370 current_modifier_map_ = modifier_map; | 485 current_modifier_map_ = modifier_map; |
| 371 return true; | 486 return true; |
| 372 } | 487 } |
| 373 return false; | 488 return false; |
| 374 } | 489 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 395 case kCapsLockKey: | 510 case kCapsLockKey: |
| 396 return "capslock"; | 511 return "capslock"; |
| 397 case kNumModifierKeys: | 512 case kNumModifierKeys: |
| 398 break; | 513 break; |
| 399 } | 514 } |
| 400 return ""; | 515 return ""; |
| 401 } | 516 } |
| 402 | 517 |
| 403 } // namespace input_method | 518 } // namespace input_method |
| 404 } // namespace chromeos | 519 } // namespace chromeos |
| OLD | NEW |