| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <cstdlib> | 7 #include <cstdlib> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <queue> | 9 #include <queue> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 // The default keyboard layout name in the xorg config file. | 34 // The default keyboard layout name in the xorg config file. |
| 35 const char kDefaultLayoutName[] = "us"; | 35 const char kDefaultLayoutName[] = "us"; |
| 36 | 36 |
| 37 // The command we use to set the current XKB layout and modifier key mapping. | 37 // The command we use to set the current XKB layout and modifier key mapping. |
| 38 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) | 38 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) |
| 39 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; | 39 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; |
| 40 | 40 |
| 41 // A string for obtaining a mask value for Num Lock. | 41 // A string for obtaining a mask value for Num Lock. |
| 42 const char kNumLockVirtualModifierString[] = "NumLock"; | 42 const char kNumLockVirtualModifierString[] = "NumLock"; |
| 43 | 43 |
| 44 // Returns false if |layout_name| contains a bad character. |
| 45 bool CheckLayoutName(const std::string& layout_name) { |
| 46 static const char kValidLayoutNameCharacters[] = |
| 47 "abcdefghijklmnopqrstuvwxyz0123456789()-_"; |
| 48 |
| 49 if (layout_name.empty()) { |
| 50 DVLOG(1) << "Invalid layout_name: " << layout_name; |
| 51 return false; |
| 52 } |
| 53 |
| 54 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) != |
| 55 std::string::npos) { |
| 56 DVLOG(1) << "Invalid layout_name: " << layout_name; |
| 57 return false; |
| 58 } |
| 59 |
| 60 return true; |
| 61 } |
| 62 |
| 44 class XKeyboardImpl : public XKeyboard { | 63 class XKeyboardImpl : public XKeyboard { |
| 45 public: | 64 public: |
| 46 explicit XKeyboardImpl(const InputMethodUtil& util); | 65 explicit XKeyboardImpl(const InputMethodUtil& util); |
| 47 virtual ~XKeyboardImpl() {} | 66 virtual ~XKeyboardImpl() {} |
| 48 | 67 |
| 49 // Overridden from XKeyboard: | 68 // Overridden from XKeyboard: |
| 50 virtual bool SetCurrentKeyboardLayoutByName( | 69 virtual bool SetCurrentKeyboardLayoutByName( |
| 51 const std::string& layout_name) OVERRIDE; | 70 const std::string& layout_name) OVERRIDE; |
| 52 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE; | 71 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE; |
| 53 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE; | 72 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE; |
| 54 virtual void SetLockedModifiers( | 73 virtual void SetLockedModifiers( |
| 55 ModifierLockStatus new_caps_lock_status, | 74 ModifierLockStatus new_caps_lock_status, |
| 56 ModifierLockStatus new_num_lock_status) OVERRIDE; | 75 ModifierLockStatus new_num_lock_status) OVERRIDE; |
| 57 virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE; | 76 virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE; |
| 58 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE; | 77 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE; |
| 59 virtual bool NumLockIsEnabled() OVERRIDE; | 78 virtual bool NumLockIsEnabled() OVERRIDE; |
| 60 virtual bool CapsLockIsEnabled() OVERRIDE; | 79 virtual bool CapsLockIsEnabled() OVERRIDE; |
| 61 virtual unsigned int GetNumLockMask() OVERRIDE; | 80 virtual unsigned int GetNumLockMask() OVERRIDE; |
| 62 virtual void GetLockedModifiers(bool* out_caps_lock_enabled, | 81 virtual void GetLockedModifiers(bool* out_caps_lock_enabled, |
| 63 bool* out_num_lock_enabled) OVERRIDE; | 82 bool* out_num_lock_enabled) OVERRIDE; |
| 64 virtual std::string CreateFullXkbLayoutName( | |
| 65 const std::string& layout_name) OVERRIDE; | |
| 66 | 83 |
| 67 private: | 84 private: |
| 68 // This function is used by SetLayout() and RemapModifierKeys(). Calls | 85 // This function is used by SetLayout() and RemapModifierKeys(). Calls |
| 69 // setxkbmap command if needed, and updates the last_full_layout_name_ cache. | 86 // setxkbmap command if needed, and updates the last_full_layout_name_ cache. |
| 70 bool SetLayoutInternal(const std::string& layout_name, bool force); | 87 bool SetLayoutInternal(const std::string& layout_name, bool force); |
| 71 | 88 |
| 72 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name | 89 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name |
| 73 // in the |execute_queue_|. Do nothing if the queue is empty. | 90 // in the |execute_queue_|. Do nothing if the queue is empty. |
| 74 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) | 91 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) |
| 75 void MaybeExecuteSetLayoutCommand(); | 92 void MaybeExecuteSetLayoutCommand(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 } | 126 } |
| 110 | 127 |
| 111 bool XKeyboardImpl::SetLayoutInternal(const std::string& layout_name, | 128 bool XKeyboardImpl::SetLayoutInternal(const std::string& layout_name, |
| 112 bool force) { | 129 bool force) { |
| 113 if (!is_running_on_chrome_os_) { | 130 if (!is_running_on_chrome_os_) { |
| 114 // We should not try to change a layout on Linux or inside ui_tests. Just | 131 // We should not try to change a layout on Linux or inside ui_tests. Just |
| 115 // return true. | 132 // return true. |
| 116 return true; | 133 return true; |
| 117 } | 134 } |
| 118 | 135 |
| 119 const std::string layout_to_set = CreateFullXkbLayoutName(layout_name); | 136 if (!CheckLayoutName(layout_name)) |
| 120 if (layout_to_set.empty()) | |
| 121 return false; | 137 return false; |
| 122 | 138 |
| 123 if (!current_layout_name_.empty()) { | 139 if (!force && (current_layout_name_ == layout_name)) { |
| 124 const std::string current_layout = CreateFullXkbLayoutName( | 140 DVLOG(1) << "The requested layout is already set: " << layout_name; |
| 125 current_layout_name_); | 141 return true; |
| 126 if (!force && (current_layout == layout_to_set)) { | |
| 127 DVLOG(1) << "The requested layout is already set: " << layout_to_set; | |
| 128 return true; | |
| 129 } | |
| 130 } | 142 } |
| 131 | 143 |
| 132 DVLOG(1) << (force ? "Reapply" : "Set") << " layout: " << layout_to_set; | 144 DVLOG(1) << (force ? "Reapply" : "Set") << " layout: " << layout_name; |
| 133 | 145 |
| 134 const bool start_execution = execute_queue_.empty(); | 146 const bool start_execution = execute_queue_.empty(); |
| 135 // If no setxkbmap command is in flight (i.e. start_execution is true), | 147 // If no setxkbmap command is in flight (i.e. start_execution is true), |
| 136 // start the first one by explicitly calling MaybeExecuteSetLayoutCommand(). | 148 // start the first one by explicitly calling MaybeExecuteSetLayoutCommand(). |
| 137 // If one or more setxkbmap commands are already in flight, just push the | 149 // If one or more setxkbmap commands are already in flight, just push the |
| 138 // layout name to the queue. setxkbmap command for the layout will be called | 150 // layout name to the queue. setxkbmap command for the layout will be called |
| 139 // via OnSetLayoutFinish() callback later. | 151 // via OnSetLayoutFinish() callback later. |
| 140 execute_queue_.push(layout_to_set); | 152 execute_queue_.push(layout_name); |
| 141 if (start_execution) | 153 if (start_execution) |
| 142 MaybeExecuteSetLayoutCommand(); | 154 MaybeExecuteSetLayoutCommand(); |
| 143 | 155 |
| 144 return true; | 156 return true; |
| 145 } | 157 } |
| 146 | 158 |
| 147 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name | 159 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name |
| 148 // in the |execute_queue_|. Do nothing if the queue is empty. | 160 // in the |execute_queue_|. Do nothing if the queue is empty. |
| 149 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) | 161 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) |
| 150 void XKeyboardImpl::MaybeExecuteSetLayoutCommand() { | 162 void XKeyboardImpl::MaybeExecuteSetLayoutCommand() { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 } | 244 } |
| 233 | 245 |
| 234 XkbStateRec status; | 246 XkbStateRec status; |
| 235 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); | 247 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); |
| 236 if (out_caps_lock_enabled) | 248 if (out_caps_lock_enabled) |
| 237 *out_caps_lock_enabled = status.locked_mods & LockMask; | 249 *out_caps_lock_enabled = status.locked_mods & LockMask; |
| 238 if (out_num_lock_enabled) | 250 if (out_num_lock_enabled) |
| 239 *out_num_lock_enabled = status.locked_mods & num_lock_mask_; | 251 *out_num_lock_enabled = status.locked_mods & num_lock_mask_; |
| 240 } | 252 } |
| 241 | 253 |
| 242 std::string XKeyboardImpl::CreateFullXkbLayoutName( | |
| 243 const std::string& layout_name) { | |
| 244 static const char kValidLayoutNameCharacters[] = | |
| 245 "abcdefghijklmnopqrstuvwxyz0123456789()-_"; | |
| 246 | |
| 247 if (layout_name.empty()) { | |
| 248 DVLOG(1) << "Invalid layout_name: " << layout_name; | |
| 249 return ""; | |
| 250 } | |
| 251 | |
| 252 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) != | |
| 253 std::string::npos) { | |
| 254 DVLOG(1) << "Invalid layout_name: " << layout_name; | |
| 255 return ""; | |
| 256 } | |
| 257 | |
| 258 // TODO(yusukes): Remove "+chromeos(...)". | |
| 259 std::string full_xkb_layout_name = | |
| 260 base::StringPrintf("%s+chromeos(search_leftcontrol_leftalt_keepralt)", | |
| 261 layout_name.c_str()); | |
| 262 | |
| 263 return full_xkb_layout_name; | |
| 264 } | |
| 265 | |
| 266 void XKeyboardImpl::SetLockedModifiers(ModifierLockStatus new_caps_lock_status, | 254 void XKeyboardImpl::SetLockedModifiers(ModifierLockStatus new_caps_lock_status, |
| 267 ModifierLockStatus new_num_lock_status) { | 255 ModifierLockStatus new_num_lock_status) { |
| 268 CHECK(CurrentlyOnUIThread()); | 256 CHECK(CurrentlyOnUIThread()); |
| 269 if (!num_lock_mask_) { | 257 if (!num_lock_mask_) { |
| 270 DVLOG(1) << "Cannot set locked modifiers. Num Lock mask unknown."; | 258 DVLOG(1) << "Cannot set locked modifiers. Num Lock mask unknown."; |
| 271 return; | 259 return; |
| 272 } | 260 } |
| 273 | 261 |
| 274 unsigned int affect_mask = 0; | 262 unsigned int affect_mask = 0; |
| 275 unsigned int value_mask = 0; | 263 unsigned int value_mask = 0; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 } | 371 } |
| 384 | 372 |
| 385 // static | 373 // static |
| 386 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) { | 374 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) { |
| 387 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, | 375 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, |
| 388 &(out_rate->initial_delay_in_ms), | 376 &(out_rate->initial_delay_in_ms), |
| 389 &(out_rate->repeat_interval_in_ms)) == True; | 377 &(out_rate->repeat_interval_in_ms)) == True; |
| 390 } | 378 } |
| 391 | 379 |
| 392 // static | 380 // static |
| 381 bool XKeyboard::CheckLayoutNameForTesting(const std::string& layout_name) { |
| 382 return CheckLayoutName(layout_name); |
| 383 } |
| 384 |
| 385 // static |
| 393 XKeyboard* XKeyboard::Create(const InputMethodUtil& util) { | 386 XKeyboard* XKeyboard::Create(const InputMethodUtil& util) { |
| 394 return new XKeyboardImpl(util); | 387 return new XKeyboardImpl(util); |
| 395 } | 388 } |
| 396 | 389 |
| 397 } // namespace input_method | 390 } // namespace input_method |
| 398 } // namespace chromeos | 391 } // namespace chromeos |
| OLD | NEW |