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