Use chromeos::Process in libchromeos.a instead of g_spawn_async.
Change the order of -l linker flags in SConstruct.chromiumos since libchromeos.a depends on libbase. Without the change, chrome fails to dlopen libcros.so.
BUG=chromium-os:12875
TEST=1) ran 'FEATURES=test emerge-x86-generic libcros' to see the library link order is correct. 2) manually checked the new code could change the layout correctly.
Change-Id: I77ea179f93fac368b76fe596db32d349911993ac
Review URL: http://codereview.chromium.org/6709058
(cherry picked from commit 1167c711c1fd411cc5437c2aab7f64d948be7f6b)
Use g_spawn_async instead of _sync to avoid blocking UI-thread.
This change does the following as well:
* Deprecate getter APIs that are currently unused.
* Stop calling 'setxkbmap -print'. Instead, just remember the last layout and modifier mappings set.
BUG=chromium-os:13029
TEST=1) manually checked 2) ran the unittest
Change-Id: If141b273c5ed455b34ae41c75f9f0e1729163e69
Review URL: http://codereview.chromium.org/6691007
(cherry picked from commit 7688b1249dba6d8ce129e220c2977845666a1aaf)
TBR=satorux
Review URL: http://codereview.chromium.org/6730052
diff --git a/SConstruct.chromiumos b/SConstruct.chromiumos
index ba2a1bf..f45b651 100644
--- a/SConstruct.chromiumos
+++ b/SConstruct.chromiumos
@@ -118,7 +118,7 @@
''')
env = base_env.Clone()
-env.Append(LIBS=['base', 'chromeos', 'rt', 'rootdev'])
+env.Append(LIBS=['chromeos', 'base', 'rt', 'rootdev'])
# glib, dbus, and ibus environment
env.ParseConfig('%s --cflags --libs dbus-1 glib-2.0 gudev-1.0 dbus-glib-1 ibus-1.0 libpcrecpp x11' % env['ENV']['PKG_CONFIG'])
@@ -166,7 +166,7 @@
env_gtest.Append(LIBS=['gtest'])
env_gtest_main = env_test.Clone()
-env_gtest_main.Append(LIBS=['gtest', 'gtest_main', 'chromeos'])
+env_gtest_main.Append(LIBS=['gtest', 'gtest_main', 'chromeos', 'base'])
env_gtest_main.ParseConfig('%s --cflags --libs libpcrecpp x11' % (
env_test['ENV']['PKG_CONFIG']))
diff --git a/chromeos_keyboard.cc b/chromeos_keyboard.cc
index 2b8014f..15a0e80 100644
--- a/chromeos_keyboard.cc
+++ b/chromeos_keyboard.cc
@@ -16,11 +16,14 @@
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_util.h"
+#include "chromeos/process.h"
namespace {
-// The command we use to set/get the current XKB layout and modifier key
-// mapping.
+// The default keyboard layout name in the xorg config file.
+const char kDefaultLayoutName[] = "us";
+// The command we use to set the current XKB layout and modifier key mapping.
+// TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap";
// See the comment at ModifierKey in the .h file.
chromeos::ModifierKey kCustomizableKeys[] = {
@@ -67,62 +70,40 @@
// Sets the current keyboard layout to |layout_name|. This function does not
// change the current mapping of the modifier keys. Returns true on success.
bool SetLayout(const std::string& layout_name) {
- // TODO(yusukes): write auto tests for the function.
- chromeos::ModifierMap modifier_map;
- if (!GetModifierMapping(&modifier_map)) {
- LOG(ERROR) << "Failed to get modifier mapping.";
- return false;
- }
- if (SetLayoutInternal(layout_name, modifier_map, true)) {
+ if (SetLayoutInternal(layout_name, current_modifier_map_, true)) {
+ current_layout_name_ = layout_name;
return true;
}
+ // TODO(satorux,yusukes): Remove +version hack.
LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option";
- return SetLayoutInternal(layout_name, modifier_map, false);
+ if (SetLayoutInternal(layout_name, current_modifier_map_, false)) {
+ current_layout_name_ = layout_name;
+ return true;
+ }
+ return false;
}
// Remaps modifier keys. This function does not change the current keyboard
// layout. Returns true on success.
bool RemapModifierKeys(const chromeos::ModifierMap& modifier_map) {
// TODO(yusukes): write auto tests for the function.
- modifier_keys_are_remapped_ = false;
- const std::string layout_name = GetLayout();
- if (layout_name.empty()) {
- return false;
- }
- if (SetLayoutInternal(layout_name, modifier_map, true)) {
- modifier_keys_are_remapped_ = true;
+ if (SetLayoutInternal(current_layout_name_, modifier_map, true)) {
+ current_modifier_map_ = modifier_map;
return true;
}
+ // TODO(satorux,yusukes): Remove +version hack.
LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option";
- if (SetLayoutInternal(layout_name, modifier_map, false)) {
- modifier_keys_are_remapped_ = true;
+ if (SetLayoutInternal(current_layout_name_, modifier_map, false)) {
+ current_modifier_map_ = modifier_map;
return true;
}
return false;
}
- // Returns the current layout name like "us". On error, returns "".
- std::string GetLayout() {
- // TODO(yusukes): write auto tests for the function.
- std::string command_output = last_full_layout_name_;
-
- if (command_output.empty()) {
- // Cache is not available. Execute setxkbmap to get the current layout.
- if (!ExecuteGetLayoutCommand(&command_output)) {
- return "";
- }
- }
-
- const std::string layout_name =
- chromeos::ExtractLayoutNameFromFullXkbLayoutName(command_output);
- LOG(INFO) << "Current XKB layout name: " << layout_name;
- return layout_name;
- }
-
// Gets the current auto-repeat mode of the keyboard. The result is stored in
// |mode|. Returns true on success.
+ // TODO(yusukes): Remove this function.
bool GetAutoRepeatEnabled(bool* enabled) {
- // TODO(yusukes): write auto tests for the function.
DCHECK(enabled);
ScopedDisplay display(XOpenDisplay(NULL));
if (!display.get()) {
@@ -139,8 +120,8 @@
}
// Turns on and off the auto-repeat of the keyboard. Returns true on success.
+ // TODO(yusukes): Remove this function.
bool SetAutoRepeatEnabled(bool enabled) {
- // TODO(yusukes): write auto tests for the function.
ScopedDisplay display(XOpenDisplay(NULL));
if (!display.get()) {
return false;
@@ -156,8 +137,8 @@
// Gets the current auto-repeat rate of the keyboard. The result is stored in
// |out_rate|. Returns true on success.
+ // TODO(yusukes): Remove this function.
bool GetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
- // TODO(yusukes): write auto tests for the function.
ScopedDisplay display(XOpenDisplay(NULL));
if (!display.get()) {
return false;
@@ -174,6 +155,7 @@
// Sets the auto-repeat rate of the keyboard, initial delay in ms, and repeat
// interval in ms. Returns true on success.
+ // TODO(yusukes): Call this function in non-UI thread or in an idle callback.
bool SetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) {
// TODO(yusukes): write auto tests for the function.
ScopedDisplay display(XOpenDisplay(NULL));
@@ -196,40 +178,15 @@
private:
friend struct DefaultSingletonTraits<XKeyboard>;
- XKeyboard() : modifier_keys_are_remapped_(false) {
- InitializeStringToModifierMap(&string_to_modifier_map_);
+ XKeyboard() : current_layout_name_(kDefaultLayoutName) {
+ for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
+ chromeos::ModifierKey key = kCustomizableKeys[i];
+ current_modifier_map_.push_back(chromeos::ModifierKeyPair(key, key));
+ }
}
~XKeyboard() {
}
- // Gets the current modifier mapping and stores them on |out_modifier_map|.
- bool GetModifierMapping(chromeos::ModifierMap* out_modifier_map) {
- out_modifier_map->clear();
-
- // If modifier keys are not remapped, return a map that doesn't change
- // any key mappings.
- if (!modifier_keys_are_remapped_) {
- for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
- chromeos::ModifierKey key = kCustomizableKeys[i];
- out_modifier_map->push_back(chromeos::ModifierKeyPair(key, key));
- }
- return true;
- }
-
- std::string command_output = last_full_layout_name_;
- if (command_output.empty()) {
- // Cache is not available. Execute setxkbmap to get the current mapping.
- if (!ExecuteGetLayoutCommand(&command_output)) {
- return false;
- }
- }
- if (!chromeos::ExtractModifierMapFromFullXkbLayoutName(
- command_output, string_to_modifier_map_, out_modifier_map)) {
- return false;
- }
- return true;
- }
-
// This function is used by SetLayout() and RemapModifierKeys(). Calls
// setxkbmap command if needed, and updates the last_full_layout_name_ cache.
// If |use_version| is false, the function does not add "+version(...)" to the
@@ -243,10 +200,9 @@
return false;
}
- // Since executing setxkbmap takes more than 200 ms on EeePC, and this
- // function is called on every focus-in event, try to reduce the number of
- // the fork/exec calls.
- if (last_full_layout_name_ == layouts_to_set) {
+ const std::string current_layout = chromeos::CreateFullXkbLayoutName(
+ current_layout_name_, current_modifier_map_, use_version);
+ if (current_layout == layouts_to_set) {
DLOG(INFO) << "The requested layout is already set: " << layouts_to_set;
return true;
}
@@ -257,106 +213,36 @@
chromeos::SetCapsLockEnabled(false);
}
- gint exit_status = -1;
- const gboolean successful =
- ExecuteSetLayoutCommand(layouts_to_set, &exit_status);
-
- // On success, update the cache and return true.
- if (successful && (exit_status == 0)) {
- last_full_layout_name_ = layouts_to_set;
- DLOG(INFO) << "XKB layout is changed to " << layouts_to_set;
- return true;
- }
-
- LOG(ERROR) << "Failed to change XKB layout to: " << layouts_to_set;
- last_full_layout_name_.clear(); // invalidate the cache.
- return false;
- }
-
- // Executes 'setxkbmap -layout ...' command. Returns true if execve suceeds.
- bool ExecuteSetLayoutCommand(const std::string& layouts_to_set,
- gint* out_exit_status) {
- *out_exit_status = -1;
-
- gchar* argv[] = {
- g_strdup(kSetxkbmapCommand), g_strdup("-layout"),
- g_strdup(layouts_to_set.c_str()), NULL
- };
- GError* error = NULL;
- const gboolean successful = g_spawn_sync(NULL, argv, NULL,
- static_cast<GSpawnFlags>(0),
- NULL, NULL, NULL, NULL,
- out_exit_status, &error);
- for (size_t i = 0; argv[i] != NULL; ++i) {
- g_free(argv[i]);
- }
-
- if (!successful) {
- if (error && error->message) {
- LOG(ERROR) << "Failed to execute setxkbmap: " << error->message;
- }
- g_error_free(error);
- }
- return (successful == TRUE);
- }
-
- // Executes 'setxkbmap -print' command and parses the output (stdout) from the
- // command. Returns true if both execve and parsing the output succeed.
- // On success, it stores a string like "us+chromeos(..)+version(..)+inet(..)"
- // on |out_command_output|.
- bool ExecuteGetLayoutCommand(std::string* out_command_output) {
- out_command_output->clear();
-
- gint exit_status = -1;
- gchar* argv[] = { g_strdup(kSetxkbmapCommand), g_strdup("-print"), NULL };
- gchar* raw_command_output = NULL;
- GError* error = NULL;
- const gboolean successful = g_spawn_sync(NULL, argv, NULL,
- static_cast<GSpawnFlags>(0),
- NULL, NULL,
- &raw_command_output, NULL,
- &exit_status, &error);
- for (size_t i = 0; argv[i] != NULL; ++i) {
- g_free(argv[i]);
- }
-
- if (!successful) {
- if (error && error->message) {
- LOG(ERROR) << "Failed to execute setxkbmap: " << error->message;
- }
- g_error_free(error);
- return false;
- }
-
- // g_spawn_sync succeeded.
- std::string command_output = raw_command_output ? raw_command_output : "";
- g_free(raw_command_output);
- raw_command_output = NULL; // DO NOT USE |raw_command_output| below.
-
- if (exit_status != 0) {
- return false;
- }
- // Parse a line like:
- // "xkb_symbols { include "pc+us+chromeos(..)+version(..)+inet(pc105)" };"
- const size_t cursor = command_output.find("pc+");
- if (cursor == std::string::npos) {
- LOG(ERROR) << "pc+ is not found: " << command_output;
- return false;
- }
- *out_command_output = command_output.substr(cursor + 3); // Skip "pc+".
+ ExecuteSetLayoutCommand(layouts_to_set);
return true;
}
- // The XKB layout name which we set last time like
- // "us+chromeos(search_leftcontrol_leftalt)".
- std::string last_full_layout_name_;
+ // Executes 'setxkbmap -layout ...' command asynchronously.
+ // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
+ void ExecuteSetLayoutCommand(const std::string& layouts_to_set) {
+ chromeos::ProcessImpl process;
+ process.AddArg(kSetxkbmapCommand);
+ process.AddStringOption("-layout", layouts_to_set);
+ if (!process.Start()) {
+ LOG(ERROR) << "Failed to execute setxkbmap: " << layouts_to_set;
+ return;
+ }
+ // g_child_watch_add is necessary to prevent the process from becoming a
+ // zombie.
+ g_child_watch_add(process.pid(),
+ reinterpret_cast<GChildWatchFunc>(OnSetLayoutFinish),
+ this);
+ process.Release(); // do not kill the setxkbmap process on function exit.
+ }
- // A std::map that holds mappings like: "leftcontrol_disabled_leftalt" ->
- // { LEFT_CONTROL_KEY, VOID_KEY, LEFT_ALT_KEY }.
- chromeos::StringToModifierMap string_to_modifier_map_;
+ static void OnSetLayoutFinish(GPid pid, gint status, XKeyboard* self) {
+ DLOG(INFO) << "OnSetLayoutFinish: pid=" << pid;
+ }
- // True if modifier keys are remapped.
- bool modifier_keys_are_remapped_;
+ // 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.
+ chromeos::ModifierMap current_modifier_map_;
DISALLOW_COPY_AND_ASSIGN(XKeyboard);
};
@@ -440,76 +326,7 @@
return full_xkb_layout_name;
}
-std::string ExtractLayoutNameFromFullXkbLayoutName(
- const std::string& full_xkb_layout_name) {
- const size_t next_plus_pos = full_xkb_layout_name.find('+');
- if (next_plus_pos == std::string::npos) {
- LOG(ERROR) << "Bad layout name: " << full_xkb_layout_name;
- return "";
- }
- return full_xkb_layout_name.substr(0, next_plus_pos);
-}
-
-void InitializeStringToModifierMap(StringToModifierMap* out_map) {
- DCHECK(out_map);
- out_map->clear();
-
- for (int i = 0; i < static_cast<int>(kNumModifierKeys); ++i) {
- for (int j = 0; j < static_cast<int>(kNumModifierKeys); ++j) {
- for (int k = 0; k < static_cast<int>(kNumModifierKeys); ++k) {
- const std::string string_rep = StringPrintf(
- "%s_%s_%s",
- ModifierKeyToString(ModifierKey(i)).c_str(),
- ModifierKeyToString(ModifierKey(j)).c_str(),
- ModifierKeyToString(ModifierKey(k)).c_str());
- ModifierMap modifier_map;
- modifier_map.push_back(ModifierKeyPair(kSearchKey, ModifierKey(i)));
- modifier_map.push_back(
- ModifierKeyPair(kLeftControlKey, ModifierKey(j)));
- modifier_map.push_back(ModifierKeyPair(kLeftAltKey, ModifierKey(k)));
- out_map->insert(make_pair(string_rep, modifier_map));
- }
- }
- }
-}
-
-bool ExtractModifierMapFromFullXkbLayoutName(
- const std::string& full_xkb_layout_name,
- const StringToModifierMap& string_to_modifier_map,
- ModifierMap* out_modifier_map) {
- static const char kMark[] = "+chromeos(";
- const size_t kMarkLen = strlen(kMark);
-
- out_modifier_map->clear();
- const size_t mark_pos = full_xkb_layout_name.find(kMark);
- if (mark_pos == std::string::npos) {
- LOG(ERROR) << "Bad layout name: " << full_xkb_layout_name;
- return false;
- }
-
- const std::string tmp = // e.g. "leftcontrol_disabled_leftalt), us"
- full_xkb_layout_name.substr(mark_pos + kMarkLen);
- const size_t next_paren_pos = tmp.find(')');
- if (next_paren_pos == std::string::npos) {
- LOG(ERROR) << "Bad layout name: " << full_xkb_layout_name;
- return false;
- }
-
- const std::string modifier_map_string = tmp.substr(0, next_paren_pos);
- DLOG(INFO) << "Modifier mapping is: " << modifier_map_string;
-
- StringToModifierMap::const_iterator iter =
- string_to_modifier_map.find(modifier_map_string);
- if (iter == string_to_modifier_map.end()) {
- LOG(ERROR) << "Bad mapping name '" << modifier_map_string
- << "' in layout name '" << full_xkb_layout_name << "'";
- return false;
- }
-
- *out_modifier_map = iter->second;
- return true;
-}
-
+// This function is only for unittest.
bool CapsLockIsEnabled() {
ScopedDisplay display(XOpenDisplay(NULL));
if (!display.get()) {
@@ -520,6 +337,7 @@
return status.locked_mods & LockMask;
}
+// TODO(yusukes): Call this function in non-UI thread or in an idle callback.
void SetCapsLockEnabled(bool enable_caps_lock) {
ScopedDisplay display(XOpenDisplay(NULL));
if (!display.get()) {
@@ -555,16 +373,20 @@
return XKeyboard::Get()->RemapModifierKeys(modifier_map);
}
+// TODO(yusukes): Remove this function.
extern "C"
bool ChromeOSGetAutoRepeatEnabled(bool* enabled) {
return XKeyboard::Get()->GetAutoRepeatEnabled(enabled);
}
+// TODO(yusukes): We can remove this function since the default setting of the
+// repeat mode is true, and we don't change the default.
extern "C"
bool ChromeOSSetAutoRepeatEnabled(bool enabled) {
return XKeyboard::Get()->SetAutoRepeatEnabled(enabled);
}
+// TODO(yusukes): Remove this function.
extern "C"
bool ChromeOSGetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
return XKeyboard::Get()->GetAutoRepeatRate(out_rate);
diff --git a/chromeos_keyboard.h b/chromeos_keyboard.h
index 26b474f..14ef152 100644
--- a/chromeos_keyboard.h
+++ b/chromeos_keyboard.h
@@ -100,32 +100,8 @@
const ModifierMap& modifire_map,
bool use_version);
-// Returns a layout name which is used in libcros from a full XKB layout name.
-// On error, it returns an empty string.
-// Example: "gb(extd)+chromeos(leftcontrol_disabled_leftalt),us" -> "gb(extd)"
-std::string ExtractLayoutNameFromFullXkbLayoutName(
- const std::string& full_xkb_layout_name);
-
-// Initializes a std::map that holds mappings like:
-// "leftcontrol_disabled_leftalt" ->
-// {{ kSearchKey -> kLeftControlKey },
-// { kLeftControlKey -> kVoidKey },
-// { kLeftAltKey -> kLeftAltKey }}
-void InitializeStringToModifierMap(
- StringToModifierMap* out_string_to_modifier_map);
-
-// Returns a mapping of modifier keys from a full XKB layout name. Returns true
-// on success.
-// Example: "gb(extd)+chromeos(leftcontrol_disabled_leftalt),us" ->
-// {{ kSearchKey -> kLeftControlKey },
-// { kLeftControlKey -> kVoidKey },
-// { kLeftAltKey -> kLeftAltKey }}
-bool ExtractModifierMapFromFullXkbLayoutName(
- const std::string& full_xkb_layout_name,
- const StringToModifierMap& string_to_modifier_map,
- ModifierMap* out_modifier_map);
-
// Returns true if caps lock is enabled.
+// ONLY FOR UNIT TEST. DO NOT USE THIS FUNCTION.
bool CapsLockIsEnabled();
// Sets the caps lock status to |enable_caps_lock|.
diff --git a/chromeos_keyboard_unittest.cc b/chromeos_keyboard_unittest.cc
index d37f60a..ee25781 100644
--- a/chromeos_keyboard_unittest.cc
+++ b/chromeos_keyboard_unittest.cc
@@ -182,94 +182,6 @@
<< "layout: " << layout;
// All 4*3*3 layouts should be different.
EXPECT_TRUE(layouts.insert(layout).second) << "layout: " << layout;
- // Round-trip conversion should be possible.
- EXPECT_STREQ(
- "us", ExtractLayoutNameFromFullXkbLayoutName(layout).c_str())
- << "layout: " << layout;
- }
- }
- }
-}
-
-// Tests ExtractLayoutNameFromFullXkbLayoutName() function.
-TEST(ChromeOSKeyboardTest, TestExtractLayoutNameFromFullXkbLayoutName) {
- EXPECT_STREQ("us", ExtractLayoutNameFromFullXkbLayoutName(
- "us+chromeos(foo)").c_str());
- EXPECT_STREQ("us(dvorak)", ExtractLayoutNameFromFullXkbLayoutName(
- "us(dvorak)+chromeos(foo)").c_str());
- EXPECT_STREQ("", ExtractLayoutNameFromFullXkbLayoutName("").c_str());
- // ExtractLayoutNameFromFullXkbLayoutName should not accept layout without +.
- EXPECT_STREQ("", ExtractLayoutNameFromFullXkbLayoutName("us").c_str());
-}
-
-// Tests ExtractModifierMapFromFullXkbLayoutName() function.
-TEST(ChromeOSKeyboardTest, TestExtractModifierMapFromFullXkbLayoutName) {
- StringToModifierMap string_to_modifier_map;
- InitializeStringToModifierMap(&string_to_modifier_map);
-
- ModifierMap modifier_map;
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos(", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos()", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos(f", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos(foo", string_to_modifier_map, &modifier_map));
- EXPECT_FALSE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos(foo)", string_to_modifier_map, &modifier_map));
-
- EXPECT_TRUE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos(disabled_disabled_disabled)",
- string_to_modifier_map, &modifier_map));
- EXPECT_EQ(3, modifier_map.size());
- EXPECT_TRUE(CheckMap(modifier_map, kVoidKey, kVoidKey, kVoidKey));
-
- EXPECT_TRUE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos(disabled_disabled_disabled)+",
- string_to_modifier_map, &modifier_map));
- EXPECT_EQ(3, modifier_map.size());
- EXPECT_TRUE(CheckMap(modifier_map, kVoidKey, kVoidKey, kVoidKey));
-
- EXPECT_TRUE(ExtractModifierMapFromFullXkbLayoutName(
- "us(dvorak)+chromeos(disabled_disabled_disabled)+inet(pc105)",
- string_to_modifier_map, &modifier_map));
- EXPECT_EQ(3, modifier_map.size());
- EXPECT_TRUE(CheckMap(modifier_map, kVoidKey, kVoidKey, kVoidKey));
-
- EXPECT_TRUE(ExtractModifierMapFromFullXkbLayoutName(
- "+chromeos(disabled_disabled_disabled)",
- string_to_modifier_map, &modifier_map));
- EXPECT_EQ(3, modifier_map.size());
- EXPECT_TRUE(CheckMap(modifier_map, kVoidKey, kVoidKey, kVoidKey));
-
- EXPECT_TRUE(ExtractModifierMapFromFullXkbLayoutName(
- "+chromeos(disabled_disabled_disabled)+inet(pc105)",
- string_to_modifier_map, &modifier_map));
- EXPECT_EQ(3, modifier_map.size());
- EXPECT_TRUE(CheckMap(modifier_map, kVoidKey, kVoidKey, kVoidKey));
-
- // Check all cases just in case.
- for (int i = 0; i < static_cast<int>(kNumModifierKeys); ++i) {
- for (int j = 0; j < static_cast<int>(kNumModifierKeys); ++j) {
- for (int k = 0; k < static_cast<int>(kNumModifierKeys); ++k) {
- const std::string layout = CreateFullXkbLayoutName(
- "us", GetMap(ModifierKey(i), ModifierKey(j), ModifierKey(k)), true);
- EXPECT_TRUE(ExtractModifierMapFromFullXkbLayoutName(
- layout, string_to_modifier_map, &modifier_map))
- << "layout: " << layout;
- EXPECT_EQ(3, modifier_map.size()) << "layout: " << layout;
- EXPECT_TRUE(CheckMap(
- modifier_map, ModifierKey(i), ModifierKey(j), ModifierKey(k)))
- << "layout: " << layout;
}
}
}