Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: chrome/browser/chromeos/input_method/xkeyboard.cc

Issue 8356040: Reapply Caps Lock and Num Lock to core keyboard whenever new X input device is added (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move chrome_browser_main_chromeos.cc to an another CL Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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_, &current_caps_lock_status_, &current_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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/input_method/xkeyboard.h ('k') | chrome/browser/chromeos/input_method/xkeyboard_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698