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

Side by Side Diff: chromeos_keyboard.cc

Issue 6691007: Use g_spawn_async instead of _sync. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/cros.git@master
Patch Set: review fix Created 9 years, 9 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chromeos_keyboard.h ('k') | chromeos_keyboard_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS 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 "chromeos_keyboard.h" 5 #include "chromeos_keyboard.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include <X11/XKBlib.h> 9 #include <X11/XKBlib.h>
10 #include <X11/Xlib.h> 10 #include <X11/Xlib.h>
11 #include <glib.h> 11 #include <glib.h>
12 #include <stdlib.h> 12 #include <stdlib.h>
13 #include <string.h> 13 #include <string.h>
14 #include <xkeyboard_config_version.h> 14 #include <xkeyboard_config_version.h>
15 15
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/singleton.h" 17 #include "base/singleton.h"
18 #include "base/string_util.h" 18 #include "base/string_util.h"
19 19
20 namespace { 20 namespace {
21 21
22 // The command we use to set/get the current XKB layout and modifier key 22 // The default keyboard layout name in the xorg config file.
23 // mapping. 23 const char kDefaultLayoutName[] = "us";
24 // The command we use to set the current XKB layout and modifier key mapping.
25 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
24 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; 26 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap";
25 // See the comment at ModifierKey in the .h file. 27 // See the comment at ModifierKey in the .h file.
26 chromeos::ModifierKey kCustomizableKeys[] = { 28 chromeos::ModifierKey kCustomizableKeys[] = {
27 chromeos::kSearchKey, 29 chromeos::kSearchKey,
28 chromeos::kLeftControlKey, 30 chromeos::kLeftControlKey,
29 chromeos::kLeftAltKey 31 chromeos::kLeftAltKey
30 }; 32 };
31 33
32 // This is a wrapper class around Display, that opens and closes X display in 34 // This is a wrapper class around Display, that opens and closes X display in
33 // the constructor and destructor. 35 // the constructor and destructor.
(...skipping 26 matching lines...) Expand all
60 public: 62 public:
61 // Returns the singleton instance of the class. Use LeakySingletonTraits. 63 // Returns the singleton instance of the class. Use LeakySingletonTraits.
62 // We don't delete the instance at exit. 64 // We don't delete the instance at exit.
63 static XKeyboard* Get() { 65 static XKeyboard* Get() {
64 return Singleton<XKeyboard, LeakySingletonTraits<XKeyboard> >::get(); 66 return Singleton<XKeyboard, LeakySingletonTraits<XKeyboard> >::get();
65 } 67 }
66 68
67 // Sets the current keyboard layout to |layout_name|. This function does not 69 // Sets the current keyboard layout to |layout_name|. This function does not
68 // change the current mapping of the modifier keys. Returns true on success. 70 // change the current mapping of the modifier keys. Returns true on success.
69 bool SetLayout(const std::string& layout_name) { 71 bool SetLayout(const std::string& layout_name) {
70 // TODO(yusukes): write auto tests for the function. 72 if (SetLayoutInternal(layout_name, current_modifier_map_, true)) {
71 chromeos::ModifierMap modifier_map; 73 current_layout_name_ = layout_name;
72 if (!GetModifierMapping(&modifier_map)) {
73 LOG(ERROR) << "Failed to get modifier mapping.";
74 return false;
75 }
76 if (SetLayoutInternal(layout_name, modifier_map, true)) {
77 return true; 74 return true;
78 } 75 }
76 // TODO(satorux,yusukes): Remove +version hack.
79 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option"; 77 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option";
80 return SetLayoutInternal(layout_name, modifier_map, false); 78 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) {
79 current_layout_name_ = layout_name;
80 return true;
81 }
82 return false;
81 } 83 }
82 84
83 // Remaps modifier keys. This function does not change the current keyboard 85 // Remaps modifier keys. This function does not change the current keyboard
84 // layout. Returns true on success. 86 // layout. Returns true on success.
85 bool RemapModifierKeys(const chromeos::ModifierMap& modifier_map) { 87 bool RemapModifierKeys(const chromeos::ModifierMap& modifier_map) {
86 // TODO(yusukes): write auto tests for the function. 88 // TODO(yusukes): write auto tests for the function.
87 modifier_keys_are_remapped_ = false; 89 if (SetLayoutInternal(current_layout_name_, modifier_map, true)) {
88 const std::string layout_name = GetLayout(); 90 current_modifier_map_ = modifier_map;
89 if (layout_name.empty()) {
90 return false;
91 }
92 if (SetLayoutInternal(layout_name, modifier_map, true)) {
93 modifier_keys_are_remapped_ = true;
94 return true; 91 return true;
95 } 92 }
93 // TODO(satorux,yusukes): Remove +version hack.
96 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option"; 94 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option";
97 if (SetLayoutInternal(layout_name, modifier_map, false)) { 95 if (SetLayoutInternal(current_layout_name_, modifier_map, false)) {
98 modifier_keys_are_remapped_ = true; 96 current_modifier_map_ = modifier_map;
99 return true; 97 return true;
100 } 98 }
101 return false; 99 return false;
102 } 100 }
103 101
104 // Returns the current layout name like "us". On error, returns "".
105 std::string GetLayout() {
106 // TODO(yusukes): write auto tests for the function.
107 std::string command_output = last_full_layout_name_;
108
109 if (command_output.empty()) {
110 // Cache is not available. Execute setxkbmap to get the current layout.
111 if (!ExecuteGetLayoutCommand(&command_output)) {
112 return "";
113 }
114 }
115
116 const std::string layout_name =
117 chromeos::ExtractLayoutNameFromFullXkbLayoutName(command_output);
118 LOG(INFO) << "Current XKB layout name: " << layout_name;
119 return layout_name;
120 }
121
122 // Gets the current auto-repeat mode of the keyboard. The result is stored in 102 // Gets the current auto-repeat mode of the keyboard. The result is stored in
123 // |mode|. Returns true on success. 103 // |mode|. Returns true on success.
104 // TODO(yusukes): Remove this function.
124 bool GetAutoRepeatEnabled(bool* enabled) { 105 bool GetAutoRepeatEnabled(bool* enabled) {
125 // TODO(yusukes): write auto tests for the function.
126 DCHECK(enabled); 106 DCHECK(enabled);
127 ScopedDisplay display(XOpenDisplay(NULL)); 107 ScopedDisplay display(XOpenDisplay(NULL));
128 if (!display.get()) { 108 if (!display.get()) {
129 return false; 109 return false;
130 } 110 }
131 XKeyboardState values = {}; 111 XKeyboardState values = {};
132 XGetKeyboardControl(display.get(), &values); 112 XGetKeyboardControl(display.get(), &values);
133 if (values.global_auto_repeat == 0) { 113 if (values.global_auto_repeat == 0) {
134 *enabled = false; 114 *enabled = false;
135 } else { 115 } else {
136 *enabled = true; 116 *enabled = true;
137 } 117 }
138 return true; 118 return true;
139 } 119 }
140 120
141 // Turns on and off the auto-repeat of the keyboard. Returns true on success. 121 // Turns on and off the auto-repeat of the keyboard. Returns true on success.
122 // TODO(yusukes): Remove this function.
142 bool SetAutoRepeatEnabled(bool enabled) { 123 bool SetAutoRepeatEnabled(bool enabled) {
143 // TODO(yusukes): write auto tests for the function.
144 ScopedDisplay display(XOpenDisplay(NULL)); 124 ScopedDisplay display(XOpenDisplay(NULL));
145 if (!display.get()) { 125 if (!display.get()) {
146 return false; 126 return false;
147 } 127 }
148 if (enabled) { 128 if (enabled) {
149 XAutoRepeatOn(display.get()); 129 XAutoRepeatOn(display.get());
150 } else { 130 } else {
151 XAutoRepeatOff(display.get()); 131 XAutoRepeatOff(display.get());
152 } 132 }
153 DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); 133 DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
154 return true; 134 return true;
155 } 135 }
156 136
157 // Gets the current auto-repeat rate of the keyboard. The result is stored in 137 // Gets the current auto-repeat rate of the keyboard. The result is stored in
158 // |out_rate|. Returns true on success. 138 // |out_rate|. Returns true on success.
139 // TODO(yusukes): Remove this function.
159 bool GetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) { 140 bool GetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
160 // TODO(yusukes): write auto tests for the function.
161 ScopedDisplay display(XOpenDisplay(NULL)); 141 ScopedDisplay display(XOpenDisplay(NULL));
162 if (!display.get()) { 142 if (!display.get()) {
163 return false; 143 return false;
164 } 144 }
165 if (XkbGetAutoRepeatRate(display.get(), XkbUseCoreKbd, 145 if (XkbGetAutoRepeatRate(display.get(), XkbUseCoreKbd,
166 &(out_rate->initial_delay_in_ms), 146 &(out_rate->initial_delay_in_ms),
167 &(out_rate->repeat_interval_in_ms)) != True) { 147 &(out_rate->repeat_interval_in_ms)) != True) {
168 out_rate->initial_delay_in_ms = 0; 148 out_rate->initial_delay_in_ms = 0;
169 out_rate->repeat_interval_in_ms = 0; 149 out_rate->repeat_interval_in_ms = 0;
170 return false; 150 return false;
171 } 151 }
172 return true; 152 return true;
173 } 153 }
174 154
175 // Sets the auto-repeat rate of the keyboard, initial delay in ms, and repeat 155 // Sets the auto-repeat rate of the keyboard, initial delay in ms, and repeat
176 // interval in ms. Returns true on success. 156 // interval in ms. Returns true on success.
157 // TODO(yusukes): Call this function in non-UI thread or in an idle callback.
177 bool SetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) { 158 bool SetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) {
178 // TODO(yusukes): write auto tests for the function. 159 // TODO(yusukes): write auto tests for the function.
179 ScopedDisplay display(XOpenDisplay(NULL)); 160 ScopedDisplay display(XOpenDisplay(NULL));
180 if (!display.get()) { 161 if (!display.get()) {
181 return false; 162 return false;
182 } 163 }
183 164
184 DLOG(INFO) << "Set auto-repeat rate to: " 165 DLOG(INFO) << "Set auto-repeat rate to: "
185 << rate.initial_delay_in_ms << " ms delay, " 166 << rate.initial_delay_in_ms << " ms delay, "
186 << rate.repeat_interval_in_ms << " ms interval"; 167 << rate.repeat_interval_in_ms << " ms interval";
187 if (XkbSetAutoRepeatRate(display.get(), XkbUseCoreKbd, 168 if (XkbSetAutoRepeatRate(display.get(), XkbUseCoreKbd,
188 rate.initial_delay_in_ms, 169 rate.initial_delay_in_ms,
189 rate.repeat_interval_in_ms) != True) { 170 rate.repeat_interval_in_ms) != True) {
190 LOG(ERROR) << "Failed to set auto-repeat rate"; 171 LOG(ERROR) << "Failed to set auto-repeat rate";
191 return false; 172 return false;
192 } 173 }
193 return true; 174 return true;
194 } 175 }
195 176
196 private: 177 private:
197 friend struct DefaultSingletonTraits<XKeyboard>; 178 friend struct DefaultSingletonTraits<XKeyboard>;
198 179
199 XKeyboard() : modifier_keys_are_remapped_(false) { 180 XKeyboard() : current_layout_name_(kDefaultLayoutName) {
200 InitializeStringToModifierMap(&string_to_modifier_map_); 181 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
182 chromeos::ModifierKey key = kCustomizableKeys[i];
183 current_modifier_map_.push_back(chromeos::ModifierKeyPair(key, key));
184 }
201 } 185 }
202 ~XKeyboard() { 186 ~XKeyboard() {
203 } 187 }
204 188
205 // Gets the current modifier mapping and stores them on |out_modifier_map|.
206 bool GetModifierMapping(chromeos::ModifierMap* out_modifier_map) {
207 out_modifier_map->clear();
208
209 // If modifier keys are not remapped, return a map that doesn't change
210 // any key mappings.
211 if (!modifier_keys_are_remapped_) {
212 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
213 chromeos::ModifierKey key = kCustomizableKeys[i];
214 out_modifier_map->push_back(chromeos::ModifierKeyPair(key, key));
215 }
216 return true;
217 }
218
219 std::string command_output = last_full_layout_name_;
220 if (command_output.empty()) {
221 // Cache is not available. Execute setxkbmap to get the current mapping.
222 if (!ExecuteGetLayoutCommand(&command_output)) {
223 return false;
224 }
225 }
226 if (!chromeos::ExtractModifierMapFromFullXkbLayoutName(
227 command_output, string_to_modifier_map_, out_modifier_map)) {
228 return false;
229 }
230 return true;
231 }
232
233 // This function is used by SetLayout() and RemapModifierKeys(). Calls 189 // This function is used by SetLayout() and RemapModifierKeys(). Calls
234 // setxkbmap command if needed, and updates the last_full_layout_name_ cache. 190 // setxkbmap command if needed, and updates the last_full_layout_name_ cache.
235 // If |use_version| is false, the function does not add "+version(...)" to the 191 // If |use_version| is false, the function does not add "+version(...)" to the
236 // layout name. See http://crosbug.com/6261 for details. 192 // layout name. See http://crosbug.com/6261 for details.
237 bool SetLayoutInternal(const std::string& layout_name, 193 bool SetLayoutInternal(const std::string& layout_name,
238 const chromeos::ModifierMap& modifier_map, 194 const chromeos::ModifierMap& modifier_map,
239 bool use_version) { 195 bool use_version) {
240 const std::string layouts_to_set = chromeos::CreateFullXkbLayoutName( 196 const std::string layouts_to_set = chromeos::CreateFullXkbLayoutName(
241 layout_name, modifier_map, use_version); 197 layout_name, modifier_map, use_version);
242 if (layouts_to_set.empty()) { 198 if (layouts_to_set.empty()) {
243 return false; 199 return false;
244 } 200 }
245 201
246 // Since executing setxkbmap takes more than 200 ms on EeePC, and this 202 const std::string current_layout = chromeos::CreateFullXkbLayoutName(
247 // function is called on every focus-in event, try to reduce the number of 203 current_layout_name_, current_modifier_map_, use_version);
248 // the fork/exec calls. 204 if (current_layout == layouts_to_set) {
249 if (last_full_layout_name_ == layouts_to_set) {
250 DLOG(INFO) << "The requested layout is already set: " << layouts_to_set; 205 DLOG(INFO) << "The requested layout is already set: " << layouts_to_set;
251 return true; 206 return true;
252 } 207 }
253 208
254 // Turn off caps lock if there is no kCapsLockKey in the remapped keys. 209 // Turn off caps lock if there is no kCapsLockKey in the remapped keys.
255 if (!ContainsModifierKeyAsReplacement( 210 if (!ContainsModifierKeyAsReplacement(
256 modifier_map, chromeos::kCapsLockKey)) { 211 modifier_map, chromeos::kCapsLockKey)) {
257 chromeos::SetCapsLockEnabled(false); 212 chromeos::SetCapsLockEnabled(false);
258 } 213 }
259 214
260 gint exit_status = -1; 215 ExecuteSetLayoutCommand(layouts_to_set);
261 const gboolean successful = 216 return true;
262 ExecuteSetLayoutCommand(layouts_to_set, &exit_status);
263
264 // On success, update the cache and return true.
265 if (successful && (exit_status == 0)) {
266 last_full_layout_name_ = layouts_to_set;
267 DLOG(INFO) << "XKB layout is changed to " << layouts_to_set;
268 return true;
269 }
270
271 LOG(ERROR) << "Failed to change XKB layout to: " << layouts_to_set;
272 last_full_layout_name_.clear(); // invalidate the cache.
273 return false;
274 } 217 }
275 218
276 // Executes 'setxkbmap -layout ...' command. Returns true if execve suceeds. 219 // Executes 'setxkbmap -layout ...' command asynchronously.
277 bool ExecuteSetLayoutCommand(const std::string& layouts_to_set, 220 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
278 gint* out_exit_status) { 221 void ExecuteSetLayoutCommand(const std::string& layouts_to_set) {
279 *out_exit_status = -1;
280
281 gchar* argv[] = { 222 gchar* argv[] = {
282 g_strdup(kSetxkbmapCommand), g_strdup("-layout"), 223 g_strdup(kSetxkbmapCommand), g_strdup("-layout"),
283 g_strdup(layouts_to_set.c_str()), NULL 224 g_strdup(layouts_to_set.c_str()), NULL
284 }; 225 };
226
227 const GSpawnFlags flags = static_cast<GSpawnFlags>(
228 G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL);
285 GError* error = NULL; 229 GError* error = NULL;
286 const gboolean successful = g_spawn_sync(NULL, argv, NULL, 230 g_spawn_async(NULL, // working_directory
287 static_cast<GSpawnFlags>(0), 231 argv,
288 NULL, NULL, NULL, NULL, 232 NULL, // envp
289 out_exit_status, &error); 233 flags,
234 NULL, // child_setup
235 NULL, // user_data
236 NULL, // child_pid
237 &error);
238
290 for (size_t i = 0; argv[i] != NULL; ++i) { 239 for (size_t i = 0; argv[i] != NULL; ++i) {
291 g_free(argv[i]); 240 g_free(argv[i]);
292 } 241 }
293 242 if (error) {
294 if (!successful) { 243 if (error->message) {
295 if (error && error->message) {
296 LOG(ERROR) << "Failed to execute setxkbmap: " << error->message; 244 LOG(ERROR) << "Failed to execute setxkbmap: " << error->message;
297 } 245 }
298 g_error_free(error); 246 g_error_free(error);
299 } 247 }
300 return (successful == TRUE);
301 } 248 }
302 249
303 // Executes 'setxkbmap -print' command and parses the output (stdout) from the 250 // The XKB layout name which we set last time like "us" and "us(dvorak)".
304 // command. Returns true if both execve and parsing the output succeed. 251 std::string current_layout_name_;
305 // On success, it stores a string like "us+chromeos(..)+version(..)+inet(..)" 252 // The mapping of modifier keys we set last time.
306 // on |out_command_output|. 253 chromeos::ModifierMap current_modifier_map_;
307 bool ExecuteGetLayoutCommand(std::string* out_command_output) {
308 out_command_output->clear();
309
310 gint exit_status = -1;
311 gchar* argv[] = { g_strdup(kSetxkbmapCommand), g_strdup("-print"), NULL };
312 gchar* raw_command_output = NULL;
313 GError* error = NULL;
314 const gboolean successful = g_spawn_sync(NULL, argv, NULL,
315 static_cast<GSpawnFlags>(0),
316 NULL, NULL,
317 &raw_command_output, NULL,
318 &exit_status, &error);
319 for (size_t i = 0; argv[i] != NULL; ++i) {
320 g_free(argv[i]);
321 }
322
323 if (!successful) {
324 if (error && error->message) {
325 LOG(ERROR) << "Failed to execute setxkbmap: " << error->message;
326 }
327 g_error_free(error);
328 return false;
329 }
330
331 // g_spawn_sync succeeded.
332 std::string command_output = raw_command_output ? raw_command_output : "";
333 g_free(raw_command_output);
334 raw_command_output = NULL; // DO NOT USE |raw_command_output| below.
335
336 if (exit_status != 0) {
337 return false;
338 }
339 // Parse a line like:
340 // "xkb_symbols { include "pc+us+chromeos(..)+version(..)+inet(pc105)" };"
341 const size_t cursor = command_output.find("pc+");
342 if (cursor == std::string::npos) {
343 LOG(ERROR) << "pc+ is not found: " << command_output;
344 return false;
345 }
346 *out_command_output = command_output.substr(cursor + 3); // Skip "pc+".
347 return true;
348 }
349
350 // The XKB layout name which we set last time like
351 // "us+chromeos(search_leftcontrol_leftalt)".
352 std::string last_full_layout_name_;
353
354 // A std::map that holds mappings like: "leftcontrol_disabled_leftalt" ->
355 // { LEFT_CONTROL_KEY, VOID_KEY, LEFT_ALT_KEY }.
356 chromeos::StringToModifierMap string_to_modifier_map_;
357
358 // True if modifier keys are remapped.
359 bool modifier_keys_are_remapped_;
360 254
361 DISALLOW_COPY_AND_ASSIGN(XKeyboard); 255 DISALLOW_COPY_AND_ASSIGN(XKeyboard);
362 }; 256 };
363 257
364 } // namespace 258 } // namespace
365 259
366 namespace chromeos { 260 namespace chromeos {
367 261
368 std::string CreateFullXkbLayoutName(const std::string& layout_name, 262 std::string CreateFullXkbLayoutName(const std::string& layout_name,
369 const ModifierMap& modifier_map, 263 const ModifierMap& modifier_map,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 version.c_str()); 327 version.c_str());
434 328
435 if ((full_xkb_layout_name.substr(0, 3) != "us+") && 329 if ((full_xkb_layout_name.substr(0, 3) != "us+") &&
436 (full_xkb_layout_name.substr(0, 3) != "us(")) { 330 (full_xkb_layout_name.substr(0, 3) != "us(")) {
437 full_xkb_layout_name += ",us"; 331 full_xkb_layout_name += ",us";
438 } 332 }
439 333
440 return full_xkb_layout_name; 334 return full_xkb_layout_name;
441 } 335 }
442 336
443 std::string ExtractLayoutNameFromFullXkbLayoutName( 337 // This function is only for unittest.
444 const std::string& full_xkb_layout_name) {
445 const size_t next_plus_pos = full_xkb_layout_name.find('+');
446 if (next_plus_pos == std::string::npos) {
447 LOG(ERROR) << "Bad layout name: " << full_xkb_layout_name;
448 return "";
449 }
450 return full_xkb_layout_name.substr(0, next_plus_pos);
451 }
452
453 void InitializeStringToModifierMap(StringToModifierMap* out_map) {
454 DCHECK(out_map);
455 out_map->clear();
456
457 for (int i = 0; i < static_cast<int>(kNumModifierKeys); ++i) {
458 for (int j = 0; j < static_cast<int>(kNumModifierKeys); ++j) {
459 for (int k = 0; k < static_cast<int>(kNumModifierKeys); ++k) {
460 const std::string string_rep = StringPrintf(
461 "%s_%s_%s",
462 ModifierKeyToString(ModifierKey(i)).c_str(),
463 ModifierKeyToString(ModifierKey(j)).c_str(),
464 ModifierKeyToString(ModifierKey(k)).c_str());
465 ModifierMap modifier_map;
466 modifier_map.push_back(ModifierKeyPair(kSearchKey, ModifierKey(i)));
467 modifier_map.push_back(
468 ModifierKeyPair(kLeftControlKey, ModifierKey(j)));
469 modifier_map.push_back(ModifierKeyPair(kLeftAltKey, ModifierKey(k)));
470 out_map->insert(make_pair(string_rep, modifier_map));
471 }
472 }
473 }
474 }
475
476 bool ExtractModifierMapFromFullXkbLayoutName(
477 const std::string& full_xkb_layout_name,
478 const StringToModifierMap& string_to_modifier_map,
479 ModifierMap* out_modifier_map) {
480 static const char kMark[] = "+chromeos(";
481 const size_t kMarkLen = strlen(kMark);
482
483 out_modifier_map->clear();
484 const size_t mark_pos = full_xkb_layout_name.find(kMark);
485 if (mark_pos == std::string::npos) {
486 LOG(ERROR) << "Bad layout name: " << full_xkb_layout_name;
487 return false;
488 }
489
490 const std::string tmp = // e.g. "leftcontrol_disabled_leftalt), us"
491 full_xkb_layout_name.substr(mark_pos + kMarkLen);
492 const size_t next_paren_pos = tmp.find(')');
493 if (next_paren_pos == std::string::npos) {
494 LOG(ERROR) << "Bad layout name: " << full_xkb_layout_name;
495 return false;
496 }
497
498 const std::string modifier_map_string = tmp.substr(0, next_paren_pos);
499 DLOG(INFO) << "Modifier mapping is: " << modifier_map_string;
500
501 StringToModifierMap::const_iterator iter =
502 string_to_modifier_map.find(modifier_map_string);
503 if (iter == string_to_modifier_map.end()) {
504 LOG(ERROR) << "Bad mapping name '" << modifier_map_string
505 << "' in layout name '" << full_xkb_layout_name << "'";
506 return false;
507 }
508
509 *out_modifier_map = iter->second;
510 return true;
511 }
512
513 bool CapsLockIsEnabled() { 338 bool CapsLockIsEnabled() {
514 ScopedDisplay display(XOpenDisplay(NULL)); 339 ScopedDisplay display(XOpenDisplay(NULL));
515 if (!display.get()) { 340 if (!display.get()) {
516 return false; 341 return false;
517 } 342 }
518 XkbStateRec status; 343 XkbStateRec status;
519 XkbGetState(display.get(), XkbUseCoreKbd, &status); 344 XkbGetState(display.get(), XkbUseCoreKbd, &status);
520 return status.locked_mods & LockMask; 345 return status.locked_mods & LockMask;
521 } 346 }
522 347
348 // TODO(yusukes): Call this function in non-UI thread or in an idle callback.
523 void SetCapsLockEnabled(bool enable_caps_lock) { 349 void SetCapsLockEnabled(bool enable_caps_lock) {
524 ScopedDisplay display(XOpenDisplay(NULL)); 350 ScopedDisplay display(XOpenDisplay(NULL));
525 if (!display.get()) { 351 if (!display.get()) {
526 return; 352 return;
527 } 353 }
528 XkbLockModifiers( 354 XkbLockModifiers(
529 display.get(), XkbUseCoreKbd, LockMask, enable_caps_lock ? LockMask : 0); 355 display.get(), XkbUseCoreKbd, LockMask, enable_caps_lock ? LockMask : 0);
530 } 356 }
531 357
532 bool ContainsModifierKeyAsReplacement( 358 bool ContainsModifierKeyAsReplacement(
(...skipping 15 matching lines...) Expand all
548 extern "C" 374 extern "C"
549 bool ChromeOSSetCurrentKeyboardLayoutByName(const std::string& layout_name) { 375 bool ChromeOSSetCurrentKeyboardLayoutByName(const std::string& layout_name) {
550 return XKeyboard::Get()->SetLayout(layout_name); 376 return XKeyboard::Get()->SetLayout(layout_name);
551 } 377 }
552 378
553 extern "C" 379 extern "C"
554 bool ChromeOSRemapModifierKeys(const chromeos::ModifierMap& modifier_map) { 380 bool ChromeOSRemapModifierKeys(const chromeos::ModifierMap& modifier_map) {
555 return XKeyboard::Get()->RemapModifierKeys(modifier_map); 381 return XKeyboard::Get()->RemapModifierKeys(modifier_map);
556 } 382 }
557 383
384 // TODO(yusukes): Remove this function.
558 extern "C" 385 extern "C"
559 bool ChromeOSGetAutoRepeatEnabled(bool* enabled) { 386 bool ChromeOSGetAutoRepeatEnabled(bool* enabled) {
560 return XKeyboard::Get()->GetAutoRepeatEnabled(enabled); 387 return XKeyboard::Get()->GetAutoRepeatEnabled(enabled);
561 } 388 }
562 389
390 // TODO(yusukes): We can remove this function since the default setting of the
391 // repeat mode is true, and we don't change the default.
563 extern "C" 392 extern "C"
564 bool ChromeOSSetAutoRepeatEnabled(bool enabled) { 393 bool ChromeOSSetAutoRepeatEnabled(bool enabled) {
565 return XKeyboard::Get()->SetAutoRepeatEnabled(enabled); 394 return XKeyboard::Get()->SetAutoRepeatEnabled(enabled);
566 } 395 }
567 396
397 // TODO(yusukes): Remove this function.
568 extern "C" 398 extern "C"
569 bool ChromeOSGetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) { 399 bool ChromeOSGetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
570 return XKeyboard::Get()->GetAutoRepeatRate(out_rate); 400 return XKeyboard::Get()->GetAutoRepeatRate(out_rate);
571 } 401 }
572 402
573 extern "C" 403 extern "C"
574 bool ChromeOSSetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) { 404 bool ChromeOSSetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) {
575 return XKeyboard::Get()->SetAutoRepeatRate(rate); 405 return XKeyboard::Get()->SetAutoRepeatRate(rate);
576 } 406 }
OLDNEW
« no previous file with comments | « chromeos_keyboard.h ('k') | chromeos_keyboard_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698