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

Unified Diff: chrome/browser/chromeos/input_method/xkeyboard.cc

Issue 9264004: Make almost all public functions in XKeyboard pure virtual (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 11 months 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/input_method/xkeyboard.cc
diff --git a/chrome/browser/chromeos/input_method/xkeyboard.cc b/chrome/browser/chromeos/input_method/xkeyboard.cc
index 2f1d3db9d22635ff6a0786d7a733be831fc3246e..29593da4bd76103c87a69cccc9df811305ff1b31 100644
--- a/chrome/browser/chromeos/input_method/xkeyboard.cc
+++ b/chrome/browser/chromeos/input_method/xkeyboard.cc
@@ -4,14 +4,12 @@
#include "chrome/browser/chromeos/input_method/xkeyboard.h"
+#include <cstdlib>
+#include <cstring>
#include <queue>
#include <set>
-#include <string>
#include <utility>
-#include <stdlib.h>
-#include <string.h>
-
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/process_util.h"
@@ -101,9 +99,80 @@ const char* kCapsLockRemapped[] = {
// A string for obtaining a mask value for Num Lock.
const char kNumLockVirtualModifierString[] = "NumLock";
-} // namespace
+class XKeyboardImpl : public XKeyboard {
+ public:
+ explicit XKeyboardImpl(const InputMethodUtil& util);
+ virtual ~XKeyboardImpl() {}
+
+ // Overridden from XKeyboard:
+ virtual bool SetCurrentKeyboardLayoutByName(
+ const std::string& layout_name) OVERRIDE;
+ virtual bool RemapModifierKeys(const ModifierMap& modifier_map) OVERRIDE;
+ virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE;
+ virtual void ReapplyCurrentModifierLockStatus() OVERRIDE;
+ virtual void SetLockedModifiers(
+ ModifierLockStatus new_caps_lock_status,
+ ModifierLockStatus new_num_lock_status) OVERRIDE;
+ virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE;
+ virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE;
+ virtual bool NumLockIsEnabled() OVERRIDE;
+ virtual bool CapsLockIsEnabled() OVERRIDE;
+ virtual unsigned int GetNumLockMask() OVERRIDE;
+ virtual void GetLockedModifiers(bool* out_caps_lock_enabled,
+ bool* out_num_lock_enabled) OVERRIDE;
+ virtual std::string CreateFullXkbLayoutName(
+ const std::string& layout_name,
+ const ModifierMap& modifire_map) OVERRIDE;
+
+ private:
+ // This function is used by SetLayout() and RemapModifierKeys(). Calls
+ // setxkbmap command if needed, and updates the last_full_layout_name_ cache.
+ bool SetLayoutInternal(const std::string& layout_name,
+ const ModifierMap& modifier_map,
+ bool force);
+
+ // Executes 'setxkbmap -layout ...' command asynchronously using a layout name
+ // in the |execute_queue_|. Do nothing if the queue is empty.
+ // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
+ void MaybeExecuteSetLayoutCommand();
+
+ // Returns true if the XKB layout uses the right Alt key for special purposes
+ // like AltGr.
+ bool KeepRightAlt(const std::string& xkb_layout_name) const;
+
+ // Returns true if the XKB layout uses the CapsLock key for special purposes.
+ // For example, since US Colemak layout uses the key as back space,
+ // KeepCapsLock("us(colemak)") would return true.
+ bool KeepCapsLock(const std::string& xkb_layout_name) const;
+
+ // Converts |key| to a modifier key name which is used in
+ // /usr/share/X11/xkb/symbols/chromeos.
+ static std::string ModifierKeyToString(ModifierKey key);
+
+ // Called when execve'd setxkbmap process exits.
+ static void OnSetLayoutFinish(pid_t pid, int status, XKeyboardImpl* self);
+
+ const bool is_running_on_chrome_os_;
+ unsigned int num_lock_mask_;
+
+ // The current Num Lock and Caps Lock status. If true, enabled.
+ bool current_num_lock_status_;
+ bool current_caps_lock_status_;
+ // The XKB layout name which we set last time like "us" and "us(dvorak)".
+ std::string current_layout_name_;
+ // The mapping of modifier keys we set last time.
+ ModifierMap current_modifier_map_;
+
+ // A queue for executing setxkbmap one by one.
+ std::queue<std::string> execute_queue_;
+
+ std::set<std::string> keep_right_alt_xkb_layout_names_;
+ std::set<std::string> caps_lock_remapped_xkb_layout_names_;
+
+ DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl);
+};
-XKeyboard::XKeyboard(const InputMethodUtil& util)
+XKeyboardImpl::XKeyboardImpl(const InputMethodUtil& util)
: is_running_on_chrome_os_(
system::runtime_environment::IsRunningOnChromeOS()) {
num_lock_mask_ = GetNumLockMask();
@@ -116,8 +185,7 @@ XKeyboard::XKeyboard(const InputMethodUtil& util)
CHECK(!is_running_on_chrome_os_ || (num_lock_mask_ == Mod2Mask));
#endif
- GetLockedModifiers(
- num_lock_mask_, &current_caps_lock_status_, &current_num_lock_status_);
+ GetLockedModifiers(&current_caps_lock_status_, &current_num_lock_status_);
for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
ModifierKey key = kCustomizableKeys[i];
@@ -144,47 +212,9 @@ XKeyboard::XKeyboard(const InputMethodUtil& util)
}
}
-XKeyboard::~XKeyboard() {
-}
-
-// static
-unsigned int XKeyboard::GetNumLockMask() {
- static const unsigned int kBadMask = 0;
-
- unsigned int real_mask = kBadMask;
- XkbDescPtr xkb_desc =
- XkbGetKeyboard(ui::GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd);
- if (!xkb_desc) {
- return kBadMask;
- }
-
- if (xkb_desc->dpy && xkb_desc->names && xkb_desc->names->vmods) {
- const std::string string_to_find(kNumLockVirtualModifierString);
- for (size_t i = 0; i < XkbNumVirtualMods; ++i) {
- const unsigned int virtual_mod_mask = 1U << i;
- char* virtual_mod_str =
- XGetAtomName(xkb_desc->dpy, xkb_desc->names->vmods[i]);
- if (!virtual_mod_str) {
- continue;
- }
- if (string_to_find == virtual_mod_str) {
- if (!XkbVirtualModsToReal(xkb_desc, virtual_mod_mask, &real_mask)) {
- LOG(ERROR) << "XkbVirtualModsToReal failed";
- real_mask = kBadMask; // reset the return value, just in case.
- }
- XFree(virtual_mod_str);
- break;
- }
- XFree(virtual_mod_str);
- }
- }
- XkbFreeKeyboard(xkb_desc, 0, True /* free all components */);
- return real_mask;
-}
-
-bool XKeyboard::SetLayoutInternal(const std::string& layout_name,
- const ModifierMap& modifier_map,
- bool force) {
+bool XKeyboardImpl::SetLayoutInternal(const std::string& layout_name,
+ const ModifierMap& modifier_map,
+ bool force) {
if (!is_running_on_chrome_os_) {
// We should not try to change a layout on Linux or inside ui_tests. Just
// return true.
@@ -229,7 +259,7 @@ bool XKeyboard::SetLayoutInternal(const std::string& layout_name,
// Executes 'setxkbmap -layout ...' command asynchronously using a layout name
// in the |execute_queue_|. Do nothing if the queue is empty.
// TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
-void XKeyboard::MaybeExecuteSetLayoutCommand() {
+void XKeyboardImpl::MaybeExecuteSetLayoutCommand() {
if (execute_queue_.empty()) {
return;
}
@@ -258,21 +288,84 @@ void XKeyboard::MaybeExecuteSetLayoutCommand() {
VLOG(1) << "ExecuteSetLayoutCommand: " << layout_to_set << ": pid=" << pid;
}
-// static
-void XKeyboard::OnSetLayoutFinish(pid_t pid, int status, XKeyboard* self) {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- VLOG(1) << "OnSetLayoutFinish: pid=" << pid;
- if (self->execute_queue_.empty()) {
- LOG(ERROR) << "OnSetLayoutFinish: execute_queue_ is empty. "
- << "base::LaunchProcess failed? pid=" << pid;
+bool XKeyboardImpl::NumLockIsEnabled() {
+ bool num_lock_enabled = false;
+ GetLockedModifiers(NULL /* Caps Lock */, &num_lock_enabled);
+ return num_lock_enabled;
+}
+
+bool XKeyboardImpl::CapsLockIsEnabled() {
+ bool caps_lock_enabled = false;
+ GetLockedModifiers(&caps_lock_enabled, NULL /* Num Lock */);
+ return caps_lock_enabled;
+}
+
+unsigned int XKeyboardImpl::GetNumLockMask() {
+ static const unsigned int kBadMask = 0;
+
+ unsigned int real_mask = kBadMask;
+ XkbDescPtr xkb_desc =
+ XkbGetKeyboard(ui::GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd);
+ if (!xkb_desc) {
+ return kBadMask;
+ }
+
+ if (xkb_desc->dpy && xkb_desc->names && xkb_desc->names->vmods) {
+ const std::string string_to_find(kNumLockVirtualModifierString);
+ for (size_t i = 0; i < XkbNumVirtualMods; ++i) {
+ const unsigned int virtual_mod_mask = 1U << i;
+ char* virtual_mod_str =
+ XGetAtomName(xkb_desc->dpy, xkb_desc->names->vmods[i]);
+ if (!virtual_mod_str) {
+ continue;
+ }
+ if (string_to_find == virtual_mod_str) {
+ if (!XkbVirtualModsToReal(xkb_desc, virtual_mod_mask, &real_mask)) {
+ LOG(ERROR) << "XkbVirtualModsToReal failed";
+ real_mask = kBadMask; // reset the return value, just in case.
+ }
+ XFree(virtual_mod_str);
+ break;
+ }
+ XFree(virtual_mod_str);
+ }
+ }
+ XkbFreeKeyboard(xkb_desc, 0, True /* free all components */);
+ return real_mask;
+}
+
+void XKeyboardImpl::GetLockedModifiers(bool* out_caps_lock_enabled,
+ bool* out_num_lock_enabled) {
+ // For now, don't call CHECK() here to make
+ // TabRestoreServiceTest.DontRestorePrintPreviewTab test happy.
+ // TODO(yusukes): Fix the test, then fix the if(!BrowserThread...) line below.
+ // CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI) ||
+ (out_num_lock_enabled && !num_lock_mask_)) {
+ LOG(ERROR) << "Cannot get locked modifiers.";
+ if (out_caps_lock_enabled) {
+ *out_caps_lock_enabled = false;
+ }
+ if (out_num_lock_enabled) {
+ *out_num_lock_enabled = false;
+ }
return;
}
- self->execute_queue_.pop();
- self->MaybeExecuteSetLayoutCommand();
+
+ XkbStateRec status;
+ XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status);
+ if (out_caps_lock_enabled) {
+ *out_caps_lock_enabled = status.locked_mods & LockMask;
+ }
+ if (out_num_lock_enabled) {
+ *out_num_lock_enabled = status.locked_mods & num_lock_mask_;
+ }
}
-std::string XKeyboard::CreateFullXkbLayoutName(
- const std::string& layout_name, const ModifierMap& modifier_map) {
+std::string XKeyboardImpl::CreateFullXkbLayoutName(
+ const std::string& layout_name,
+ const ModifierMap& modifier_map) {
static const char kValidLayoutNameCharacters[] =
"abcdefghijklmnopqrstuvwxyz0123456789()-_";
@@ -346,49 +439,8 @@ std::string XKeyboard::CreateFullXkbLayoutName(
return full_xkb_layout_name;
}
-// static
-bool XKeyboard::SetAutoRepeatEnabled(bool enabled) {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (enabled) {
- XAutoRepeatOn(ui::GetXDisplay());
- } else {
- XAutoRepeatOff(ui::GetXDisplay());
- }
- DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
- return true;
-}
-
-// static
-bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DLOG(INFO) << "Set auto-repeat rate to: "
- << rate.initial_delay_in_ms << " ms delay, "
- << rate.repeat_interval_in_ms << " ms interval";
- if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
- rate.initial_delay_in_ms,
- rate.repeat_interval_in_ms) != True) {
- LOG(ERROR) << "Failed to set auto-repeat rate";
- return false;
- }
- return true;
-}
-
-// static
-bool XKeyboard::GetAutoRepeatEnabled() {
- XKeyboardState state = {};
- XGetKeyboardControl(ui::GetXDisplay(), &state);
- return state.global_auto_repeat != AutoRepeatModeOff;
-}
-
-// static
-bool XKeyboard::GetAutoRepeatRate(AutoRepeatRate* out_rate) {
- return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
- &(out_rate->initial_delay_in_ms),
- &(out_rate->repeat_interval_in_ms)) == True;
-}
-
-void XKeyboard::SetLockedModifiers(ModifierLockStatus new_caps_lock_status,
- ModifierLockStatus new_num_lock_status) {
+void XKeyboardImpl::SetLockedModifiers(ModifierLockStatus new_caps_lock_status,
+ ModifierLockStatus new_num_lock_status) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!num_lock_mask_) {
LOG(ERROR) << "Cannot set locked modifiers. Num Lock mask unknown.";
@@ -413,73 +465,18 @@ void XKeyboard::SetLockedModifiers(ModifierLockStatus new_caps_lock_status,
}
}
-void XKeyboard::SetNumLockEnabled(bool enable_num_lock) {
+void XKeyboardImpl::SetNumLockEnabled(bool enable_num_lock) {
SetLockedModifiers(
kDontChange, enable_num_lock ? kEnableLock : kDisableLock);
}
-void XKeyboard::SetCapsLockEnabled(bool enable_caps_lock) {
+void XKeyboardImpl::SetCapsLockEnabled(bool enable_caps_lock) {
SetLockedModifiers(
enable_caps_lock ? kEnableLock : kDisableLock, kDontChange);
}
-// static
-void XKeyboard::GetLockedModifiers(unsigned int num_lock_mask,
- bool* out_caps_lock_enabled,
- bool* out_num_lock_enabled) {
- // For now, don't call CHECK() here to make
- // TabRestoreServiceTest.DontRestorePrintPreviewTab test happy.
- // TODO(yusukes): Fix the test, then fix the if(!BrowserThread...) line below.
- // CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI) ||
- (out_num_lock_enabled && !num_lock_mask)) {
- LOG(ERROR) << "Cannot get locked modifiers.";
- if (out_caps_lock_enabled) {
- *out_caps_lock_enabled = false;
- }
- if (out_num_lock_enabled) {
- *out_num_lock_enabled = false;
- }
- return;
- }
-
- XkbStateRec status;
- XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status);
- if (out_caps_lock_enabled) {
- *out_caps_lock_enabled = status.locked_mods & LockMask;
- }
- if (out_num_lock_enabled) {
- *out_num_lock_enabled = status.locked_mods & num_lock_mask;
- }
-}
-
-// static
-bool XKeyboard::NumLockIsEnabled(unsigned int num_lock_mask) {
- bool num_lock_enabled = false;
- GetLockedModifiers(num_lock_mask, NULL /* Caps Lock */, &num_lock_enabled);
- return num_lock_enabled;
-}
-
-// static
-bool XKeyboard::CapsLockIsEnabled() {
- bool caps_lock_enabled = false;
- GetLockedModifiers(0, &caps_lock_enabled, NULL /* Num Lock */);
- return caps_lock_enabled;
-}
-
-// static
-bool XKeyboard::ContainsModifierKeyAsReplacement(
- const ModifierMap& modifier_map, ModifierKey key) {
- for (size_t i = 0; i < modifier_map.size(); ++i) {
- if (modifier_map[i].replacement == key) {
- return true;
- }
- }
- return false;
-}
-
-bool XKeyboard::SetCurrentKeyboardLayoutByName(const std::string& layout_name) {
+bool XKeyboardImpl::SetCurrentKeyboardLayoutByName(
+ const std::string& layout_name) {
if (SetLayoutInternal(layout_name, current_modifier_map_, false)) {
current_layout_name_ = layout_name;
return true;
@@ -487,7 +484,7 @@ bool XKeyboard::SetCurrentKeyboardLayoutByName(const std::string& layout_name) {
return false;
}
-bool XKeyboard::ReapplyCurrentKeyboardLayout() {
+bool XKeyboardImpl::ReapplyCurrentKeyboardLayout() {
if (current_layout_name_.empty()) {
LOG(ERROR) << "Can't reapply XKB layout: layout unknown";
return false;
@@ -496,12 +493,12 @@ bool XKeyboard::ReapplyCurrentKeyboardLayout() {
current_layout_name_, current_modifier_map_, true /* force */);
}
-void XKeyboard::ReapplyCurrentModifierLockStatus() {
+void XKeyboardImpl::ReapplyCurrentModifierLockStatus() {
SetLockedModifiers(current_caps_lock_status_ ? kEnableLock : kDisableLock,
current_num_lock_status_ ? kEnableLock : kDisableLock);
}
-bool XKeyboard::RemapModifierKeys(const ModifierMap& modifier_map) {
+bool XKeyboardImpl::RemapModifierKeys(const ModifierMap& modifier_map) {
const std::string layout_name = current_layout_name_.empty() ?
kDefaultLayoutName : current_layout_name_;
if (SetLayoutInternal(layout_name, modifier_map, false)) {
@@ -512,16 +509,16 @@ bool XKeyboard::RemapModifierKeys(const ModifierMap& modifier_map) {
return false;
}
-bool XKeyboard::KeepRightAlt(const std::string& xkb_layout_name) const {
+bool XKeyboardImpl::KeepRightAlt(const std::string& xkb_layout_name) const {
return keep_right_alt_xkb_layout_names_.count(xkb_layout_name) > 0;
}
-bool XKeyboard::KeepCapsLock(const std::string& xkb_layout_name) const {
+bool XKeyboardImpl::KeepCapsLock(const std::string& xkb_layout_name) const {
return caps_lock_remapped_xkb_layout_names_.count(xkb_layout_name) > 0;
}
// static
-std::string XKeyboard::ModifierKeyToString(ModifierKey key) {
+std::string XKeyboardImpl::ModifierKeyToString(ModifierKey key) {
switch (key) {
case kSearchKey:
return "search";
@@ -539,5 +536,80 @@ std::string XKeyboard::ModifierKeyToString(ModifierKey key) {
return "";
}
+// static
+void XKeyboardImpl::OnSetLayoutFinish(pid_t pid,
+ int status,
+ XKeyboardImpl* self) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ VLOG(1) << "OnSetLayoutFinish: pid=" << pid;
+ if (self->execute_queue_.empty()) {
+ LOG(ERROR) << "OnSetLayoutFinish: execute_queue_ is empty. "
+ << "base::LaunchProcess failed? pid=" << pid;
+ return;
+ }
+ self->execute_queue_.pop();
+ self->MaybeExecuteSetLayoutCommand();
+}
+
+} // namespace
+
+// static
+bool XKeyboard::SetAutoRepeatEnabled(bool enabled) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (enabled) {
+ XAutoRepeatOn(ui::GetXDisplay());
+ } else {
+ XAutoRepeatOff(ui::GetXDisplay());
+ }
+ DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
+ return true;
+}
+
+// static
+bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DLOG(INFO) << "Set auto-repeat rate to: "
+ << rate.initial_delay_in_ms << " ms delay, "
+ << rate.repeat_interval_in_ms << " ms interval";
+ if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
+ rate.initial_delay_in_ms,
+ rate.repeat_interval_in_ms) != True) {
+ LOG(ERROR) << "Failed to set auto-repeat rate";
+ return false;
+ }
+ return true;
+}
+
+// static
+bool XKeyboard::GetAutoRepeatEnabledForTesting() {
+ XKeyboardState state = {};
+ XGetKeyboardControl(ui::GetXDisplay(), &state);
+ return state.global_auto_repeat != AutoRepeatModeOff;
+}
+
+// static
+bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) {
+ return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
+ &(out_rate->initial_delay_in_ms),
+ &(out_rate->repeat_interval_in_ms)) == True;
+}
+
+// static
+bool XKeyboard::ContainsModifierKeyAsReplacement(
+ const ModifierMap& modifier_map,
+ ModifierKey key) {
+ for (size_t i = 0; i < modifier_map.size(); ++i) {
+ if (modifier_map[i].replacement == key) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// static
+XKeyboard* XKeyboard::Create(const InputMethodUtil& util) {
+ return new XKeyboardImpl(util);
+}
+
} // namespace input_method
} // namespace chromeos
« 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