| 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> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/chromeos/chromeos_version.h" | 13 #include "base/chromeos/chromeos_version.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/process_util.h" | 16 #include "base/process_util.h" |
| 17 #include "base/sequenced_task_runner.h" |
| 17 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 18 #include "base/stringprintf.h" | 19 #include "base/stringprintf.h" |
| 19 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 20 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 20 #include "content/public/browser/browser_thread.h" | |
| 21 #include "ui/base/x/x11_util.h" | 21 #include "ui/base/x/x11_util.h" |
| 22 | 22 |
| 23 // These includes conflict with base/tracked_objects.h so must come last. | 23 // These includes conflict with base/tracked_objects.h so must come last. |
| 24 #include <X11/XKBlib.h> | 24 #include <X11/XKBlib.h> |
| 25 #include <X11/Xlib.h> | 25 #include <X11/Xlib.h> |
| 26 #include <glib.h> | 26 #include <glib.h> |
| 27 | 27 |
| 28 using content::BrowserThread; | |
| 29 | |
| 30 namespace chromeos { | 28 namespace chromeos { |
| 31 namespace input_method { | 29 namespace input_method { |
| 32 namespace { | 30 namespace { |
| 33 | 31 |
| 34 // The default keyboard layout name in the xorg config file. | 32 // The default keyboard layout name in the xorg config file. |
| 35 const char kDefaultLayoutName[] = "us"; | 33 const char kDefaultLayoutName[] = "us"; |
| 36 | 34 |
| 37 // The command we use to set the current XKB layout and modifier key mapping. | 35 // 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) | 36 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) |
| 39 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; | 37 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 55 std::string::npos) { | 53 std::string::npos) { |
| 56 DVLOG(1) << "Invalid layout_name: " << layout_name; | 54 DVLOG(1) << "Invalid layout_name: " << layout_name; |
| 57 return false; | 55 return false; |
| 58 } | 56 } |
| 59 | 57 |
| 60 return true; | 58 return true; |
| 61 } | 59 } |
| 62 | 60 |
| 63 class XKeyboardImpl : public XKeyboard { | 61 class XKeyboardImpl : public XKeyboard { |
| 64 public: | 62 public: |
| 65 explicit XKeyboardImpl(const InputMethodUtil& util); | 63 explicit XKeyboardImpl( |
| 64 const InputMethodUtil& util, |
| 65 const scoped_refptr<base::SequencedTaskRunner>& default_task_runner); |
| 66 virtual ~XKeyboardImpl() {} | 66 virtual ~XKeyboardImpl() {} |
| 67 | 67 |
| 68 // Overridden from XKeyboard: | 68 // Overridden from XKeyboard: |
| 69 virtual bool SetCurrentKeyboardLayoutByName( | 69 virtual bool SetCurrentKeyboardLayoutByName( |
| 70 const std::string& layout_name) OVERRIDE; | 70 const std::string& layout_name) OVERRIDE; |
| 71 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE; | 71 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE; |
| 72 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE; | 72 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE; |
| 73 virtual void SetLockedModifiers( | 73 virtual void SetLockedModifiers( |
| 74 ModifierLockStatus new_caps_lock_status, | 74 ModifierLockStatus new_caps_lock_status, |
| 75 ModifierLockStatus new_num_lock_status) OVERRIDE; | 75 ModifierLockStatus new_num_lock_status) OVERRIDE; |
| 76 virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE; | 76 virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE; |
| 77 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE; | 77 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE; |
| 78 virtual bool NumLockIsEnabled() OVERRIDE; | 78 virtual bool NumLockIsEnabled() OVERRIDE; |
| 79 virtual bool CapsLockIsEnabled() OVERRIDE; | 79 virtual bool CapsLockIsEnabled() OVERRIDE; |
| 80 virtual unsigned int GetNumLockMask() OVERRIDE; | 80 virtual unsigned int GetNumLockMask() OVERRIDE; |
| 81 virtual void GetLockedModifiers(bool* out_caps_lock_enabled, | 81 virtual void GetLockedModifiers(bool* out_caps_lock_enabled, |
| 82 bool* out_num_lock_enabled) OVERRIDE; | 82 bool* out_num_lock_enabled) OVERRIDE; |
| 83 virtual bool SetAutoRepeatEnabled(bool enabled) OVERRIDE; |
| 84 virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) OVERRIDE; |
| 83 | 85 |
| 84 private: | 86 private: |
| 85 // This function is used by SetLayout() and RemapModifierKeys(). Calls | 87 // This function is used by SetLayout() and RemapModifierKeys(). Calls |
| 86 // setxkbmap command if needed, and updates the last_full_layout_name_ cache. | 88 // setxkbmap command if needed, and updates the last_full_layout_name_ cache. |
| 87 bool SetLayoutInternal(const std::string& layout_name, bool force); | 89 bool SetLayoutInternal(const std::string& layout_name, bool force); |
| 88 | 90 |
| 89 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name | 91 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name |
| 90 // in the |execute_queue_|. Do nothing if the queue is empty. | 92 // in the |execute_queue_|. Do nothing if the queue is empty. |
| 91 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) | 93 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) |
| 92 void MaybeExecuteSetLayoutCommand(); | 94 void MaybeExecuteSetLayoutCommand(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 103 | 105 |
| 104 // The current Num Lock and Caps Lock status. If true, enabled. | 106 // The current Num Lock and Caps Lock status. If true, enabled. |
| 105 bool current_num_lock_status_; | 107 bool current_num_lock_status_; |
| 106 bool current_caps_lock_status_; | 108 bool current_caps_lock_status_; |
| 107 // The XKB layout name which we set last time like "us" and "us(dvorak)". | 109 // The XKB layout name which we set last time like "us" and "us(dvorak)". |
| 108 std::string current_layout_name_; | 110 std::string current_layout_name_; |
| 109 | 111 |
| 110 // A queue for executing setxkbmap one by one. | 112 // A queue for executing setxkbmap one by one. |
| 111 std::queue<std::string> execute_queue_; | 113 std::queue<std::string> execute_queue_; |
| 112 | 114 |
| 115 scoped_refptr<base::SequencedTaskRunner> default_task_runner_; |
| 116 |
| 113 DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl); | 117 DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl); |
| 114 }; | 118 }; |
| 115 | 119 |
| 116 XKeyboardImpl::XKeyboardImpl(const InputMethodUtil& util) | 120 XKeyboardImpl::XKeyboardImpl( |
| 117 : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()) { | 121 const InputMethodUtil& util, |
| 122 const scoped_refptr<base::SequencedTaskRunner>& default_task_runner) |
| 123 : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()), |
| 124 default_task_runner_(default_task_runner) { |
| 118 num_lock_mask_ = GetNumLockMask(); | 125 num_lock_mask_ = GetNumLockMask(); |
| 119 | 126 |
| 120 // web_input_event_aurax11.cc seems to assume that Mod2Mask is always assigned | 127 // web_input_event_aurax11.cc seems to assume that Mod2Mask is always assigned |
| 121 // to Num Lock. | 128 // to Num Lock. |
| 122 // TODO(yusukes): Check the assumption is really okay. If not, modify the Aura | 129 // TODO(yusukes): Check the assumption is really okay. If not, modify the Aura |
| 123 // code, and then remove the CHECK below. | 130 // code, and then remove the CHECK below. |
| 124 CHECK(!is_running_on_chrome_os_ || (num_lock_mask_ == Mod2Mask)); | 131 CHECK(!is_running_on_chrome_os_ || (num_lock_mask_ == Mod2Mask)); |
| 125 GetLockedModifiers(¤t_caps_lock_status_, ¤t_num_lock_status_); | 132 GetLockedModifiers(¤t_caps_lock_status_, ¤t_num_lock_status_); |
| 126 } | 133 } |
| 127 | 134 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 | 317 |
| 311 bool XKeyboardImpl::CurrentlyOnUIThread() const { | 318 bool XKeyboardImpl::CurrentlyOnUIThread() const { |
| 312 // It seems that the tot Chrome (as of Mar 7 2012) does not allow browser | 319 // It seems that the tot Chrome (as of Mar 7 2012) does not allow browser |
| 313 // tests to call BrowserThread::CurrentlyOn(). It ends up a CHECK failure: | 320 // tests to call BrowserThread::CurrentlyOn(). It ends up a CHECK failure: |
| 314 // FATAL:sequenced_worker_pool.cc | 321 // FATAL:sequenced_worker_pool.cc |
| 315 // Check failed: constructor_message_loop_.get(). | 322 // Check failed: constructor_message_loop_.get(). |
| 316 // For now, just allow unit/browser tests to call any functions in this class. | 323 // For now, just allow unit/browser tests to call any functions in this class. |
| 317 // TODO(yusukes): Stop special-casing browser_tests and remove this function. | 324 // TODO(yusukes): Stop special-casing browser_tests and remove this function. |
| 318 if (!is_running_on_chrome_os_) | 325 if (!is_running_on_chrome_os_) |
| 319 return true; | 326 return true; |
| 320 return BrowserThread::CurrentlyOn(BrowserThread::UI); | 327 return default_task_runner_->RunsTasksOnCurrentThread(); |
| 321 } | 328 } |
| 322 | 329 |
| 323 // static | 330 // static |
| 324 void XKeyboardImpl::OnSetLayoutFinish(pid_t pid, | 331 void XKeyboardImpl::OnSetLayoutFinish(pid_t pid, |
| 325 int status, | 332 int status, |
| 326 XKeyboardImpl* self) { | 333 XKeyboardImpl* self) { |
| 327 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 334 CHECK(self->default_task_runner_->RunsTasksOnCurrentThread()); |
| 328 DVLOG(1) << "OnSetLayoutFinish: pid=" << pid; | 335 DVLOG(1) << "OnSetLayoutFinish: pid=" << pid; |
| 329 if (self->execute_queue_.empty()) { | 336 if (self->execute_queue_.empty()) { |
| 330 DVLOG(1) << "OnSetLayoutFinish: execute_queue_ is empty. " | 337 DVLOG(1) << "OnSetLayoutFinish: execute_queue_ is empty. " |
| 331 << "base::LaunchProcess failed? pid=" << pid; | 338 << "base::LaunchProcess failed? pid=" << pid; |
| 332 return; | 339 return; |
| 333 } | 340 } |
| 334 self->execute_queue_.pop(); | 341 self->execute_queue_.pop(); |
| 335 self->MaybeExecuteSetLayoutCommand(); | 342 self->MaybeExecuteSetLayoutCommand(); |
| 336 } | 343 } |
| 337 | 344 |
| 338 } // namespace | 345 bool XKeyboardImpl::SetAutoRepeatEnabled(bool enabled) { |
| 339 | 346 CHECK(default_task_runner_->RunsTasksOnCurrentThread()); |
| 340 // static | |
| 341 bool XKeyboard::SetAutoRepeatEnabled(bool enabled) { | |
| 342 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 343 if (enabled) | 347 if (enabled) |
| 344 XAutoRepeatOn(ui::GetXDisplay()); | 348 XAutoRepeatOn(ui::GetXDisplay()); |
| 345 else | 349 else |
| 346 XAutoRepeatOff(ui::GetXDisplay()); | 350 XAutoRepeatOff(ui::GetXDisplay()); |
| 347 DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); | 351 DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); |
| 348 return true; | 352 return true; |
| 349 } | 353 } |
| 350 | 354 |
| 351 // static | 355 bool XKeyboardImpl::SetAutoRepeatRate(const AutoRepeatRate& rate) { |
| 352 bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) { | 356 CHECK(default_task_runner_->RunsTasksOnCurrentThread()); |
| 353 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 354 DVLOG(1) << "Set auto-repeat rate to: " | 357 DVLOG(1) << "Set auto-repeat rate to: " |
| 355 << rate.initial_delay_in_ms << " ms delay, " | 358 << rate.initial_delay_in_ms << " ms delay, " |
| 356 << rate.repeat_interval_in_ms << " ms interval"; | 359 << rate.repeat_interval_in_ms << " ms interval"; |
| 357 if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, | 360 if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, |
| 358 rate.initial_delay_in_ms, | 361 rate.initial_delay_in_ms, |
| 359 rate.repeat_interval_in_ms) != True) { | 362 rate.repeat_interval_in_ms) != True) { |
| 360 DVLOG(1) << "Failed to set auto-repeat rate"; | 363 DVLOG(1) << "Failed to set auto-repeat rate"; |
| 361 return false; | 364 return false; |
| 362 } | 365 } |
| 363 return true; | 366 return true; |
| 364 } | 367 } |
| 365 | 368 |
| 369 } // namespace |
| 370 |
| 366 // static | 371 // static |
| 367 bool XKeyboard::GetAutoRepeatEnabledForTesting() { | 372 bool XKeyboard::GetAutoRepeatEnabledForTesting() { |
| 368 XKeyboardState state = {}; | 373 XKeyboardState state = {}; |
| 369 XGetKeyboardControl(ui::GetXDisplay(), &state); | 374 XGetKeyboardControl(ui::GetXDisplay(), &state); |
| 370 return state.global_auto_repeat != AutoRepeatModeOff; | 375 return state.global_auto_repeat != AutoRepeatModeOff; |
| 371 } | 376 } |
| 372 | 377 |
| 373 // static | 378 // static |
| 374 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) { | 379 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) { |
| 375 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, | 380 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, |
| 376 &(out_rate->initial_delay_in_ms), | 381 &(out_rate->initial_delay_in_ms), |
| 377 &(out_rate->repeat_interval_in_ms)) == True; | 382 &(out_rate->repeat_interval_in_ms)) == True; |
| 378 } | 383 } |
| 379 | 384 |
| 380 // static | 385 // static |
| 381 bool XKeyboard::CheckLayoutNameForTesting(const std::string& layout_name) { | 386 bool XKeyboard::CheckLayoutNameForTesting(const std::string& layout_name) { |
| 382 return CheckLayoutName(layout_name); | 387 return CheckLayoutName(layout_name); |
| 383 } | 388 } |
| 384 | 389 |
| 385 // static | 390 // static |
| 386 XKeyboard* XKeyboard::Create(const InputMethodUtil& util) { | 391 XKeyboard* XKeyboard::Create( |
| 387 return new XKeyboardImpl(util); | 392 const InputMethodUtil& util, |
| 393 const scoped_refptr<base::SequencedTaskRunner>& default_task_runner) { |
| 394 return new XKeyboardImpl(util, default_task_runner); |
| 388 } | 395 } |
| 389 | 396 |
| 390 } // namespace input_method | 397 } // namespace input_method |
| 391 } // namespace chromeos | 398 } // namespace chromeos |
| OLD | NEW |