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

Side by Side Diff: chromeos_keyboard.cc

Issue 6730052: Use chromeos::Process in libchromeos.a instead of g_spawn_async. (Closed) Base URL: http://git.chromium.org/git/cros.git@0.11.257.B
Patch Set: 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 #include "chromeos/process.h"
19 20
20 namespace { 21 namespace {
21 22
22 // The command we use to set/get the current XKB layout and modifier key 23 // The default keyboard layout name in the xorg config file.
23 // mapping. 24 const char kDefaultLayoutName[] = "us";
25 // The command we use to set the current XKB layout and modifier key mapping.
26 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
24 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; 27 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap";
25 // See the comment at ModifierKey in the .h file. 28 // See the comment at ModifierKey in the .h file.
26 chromeos::ModifierKey kCustomizableKeys[] = { 29 chromeos::ModifierKey kCustomizableKeys[] = {
27 chromeos::kSearchKey, 30 chromeos::kSearchKey,
28 chromeos::kLeftControlKey, 31 chromeos::kLeftControlKey,
29 chromeos::kLeftAltKey 32 chromeos::kLeftAltKey
30 }; 33 };
31 34
32 // This is a wrapper class around Display, that opens and closes X display in 35 // This is a wrapper class around Display, that opens and closes X display in
33 // the constructor and destructor. 36 // the constructor and destructor.
(...skipping 26 matching lines...) Expand all
60 public: 63 public:
61 // Returns the singleton instance of the class. Use LeakySingletonTraits. 64 // Returns the singleton instance of the class. Use LeakySingletonTraits.
62 // We don't delete the instance at exit. 65 // We don't delete the instance at exit.
63 static XKeyboard* Get() { 66 static XKeyboard* Get() {
64 return Singleton<XKeyboard, LeakySingletonTraits<XKeyboard> >::get(); 67 return Singleton<XKeyboard, LeakySingletonTraits<XKeyboard> >::get();
65 } 68 }
66 69
67 // Sets the current keyboard layout to |layout_name|. This function does not 70 // 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. 71 // change the current mapping of the modifier keys. Returns true on success.
69 bool SetLayout(const std::string& layout_name) { 72 bool SetLayout(const std::string& layout_name) {
70 // TODO(yusukes): write auto tests for the function. 73 if (SetLayoutInternal(layout_name, current_modifier_map_, true)) {
71 chromeos::ModifierMap modifier_map; 74 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; 75 return true;
78 } 76 }
77 // TODO(satorux,yusukes): Remove +version hack.
79 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option"; 78 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option";
80 return SetLayoutInternal(layout_name, modifier_map, false); 79 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) {
80 current_layout_name_ = layout_name;
81 return true;
82 }
83 return false;
81 } 84 }
82 85
83 // Remaps modifier keys. This function does not change the current keyboard 86 // Remaps modifier keys. This function does not change the current keyboard
84 // layout. Returns true on success. 87 // layout. Returns true on success.
85 bool RemapModifierKeys(const chromeos::ModifierMap& modifier_map) { 88 bool RemapModifierKeys(const chromeos::ModifierMap& modifier_map) {
86 // TODO(yusukes): write auto tests for the function. 89 // TODO(yusukes): write auto tests for the function.
87 modifier_keys_are_remapped_ = false; 90 if (SetLayoutInternal(current_layout_name_, modifier_map, true)) {
88 const std::string layout_name = GetLayout(); 91 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; 92 return true;
95 } 93 }
94 // TODO(satorux,yusukes): Remove +version hack.
96 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option"; 95 LOG(ERROR) << "SetLayoutInternal failed. Retrying without +version option";
97 if (SetLayoutInternal(layout_name, modifier_map, false)) { 96 if (SetLayoutInternal(current_layout_name_, modifier_map, false)) {
98 modifier_keys_are_remapped_ = true; 97 current_modifier_map_ = modifier_map;
99 return true; 98 return true;
100 } 99 }
101 return false; 100 return false;
102 } 101 }
103 102
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 103 // Gets the current auto-repeat mode of the keyboard. The result is stored in
123 // |mode|. Returns true on success. 104 // |mode|. Returns true on success.
105 // TODO(yusukes): Remove this function.
124 bool GetAutoRepeatEnabled(bool* enabled) { 106 bool GetAutoRepeatEnabled(bool* enabled) {
125 // TODO(yusukes): write auto tests for the function.
126 DCHECK(enabled); 107 DCHECK(enabled);
127 ScopedDisplay display(XOpenDisplay(NULL)); 108 ScopedDisplay display(XOpenDisplay(NULL));
128 if (!display.get()) { 109 if (!display.get()) {
129 return false; 110 return false;
130 } 111 }
131 XKeyboardState values = {}; 112 XKeyboardState values = {};
132 XGetKeyboardControl(display.get(), &values); 113 XGetKeyboardControl(display.get(), &values);
133 if (values.global_auto_repeat == 0) { 114 if (values.global_auto_repeat == 0) {
134 *enabled = false; 115 *enabled = false;
135 } else { 116 } else {
136 *enabled = true; 117 *enabled = true;
137 } 118 }
138 return true; 119 return true;
139 } 120 }
140 121
141 // Turns on and off the auto-repeat of the keyboard. Returns true on success. 122 // Turns on and off the auto-repeat of the keyboard. Returns true on success.
123 // TODO(yusukes): Remove this function.
142 bool SetAutoRepeatEnabled(bool enabled) { 124 bool SetAutoRepeatEnabled(bool enabled) {
143 // TODO(yusukes): write auto tests for the function.
144 ScopedDisplay display(XOpenDisplay(NULL)); 125 ScopedDisplay display(XOpenDisplay(NULL));
145 if (!display.get()) { 126 if (!display.get()) {
146 return false; 127 return false;
147 } 128 }
148 if (enabled) { 129 if (enabled) {
149 XAutoRepeatOn(display.get()); 130 XAutoRepeatOn(display.get());
150 } else { 131 } else {
151 XAutoRepeatOff(display.get()); 132 XAutoRepeatOff(display.get());
152 } 133 }
153 DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); 134 DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
154 return true; 135 return true;
155 } 136 }
156 137
157 // Gets the current auto-repeat rate of the keyboard. The result is stored in 138 // Gets the current auto-repeat rate of the keyboard. The result is stored in
158 // |out_rate|. Returns true on success. 139 // |out_rate|. Returns true on success.
140 // TODO(yusukes): Remove this function.
159 bool GetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) { 141 bool GetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
160 // TODO(yusukes): write auto tests for the function.
161 ScopedDisplay display(XOpenDisplay(NULL)); 142 ScopedDisplay display(XOpenDisplay(NULL));
162 if (!display.get()) { 143 if (!display.get()) {
163 return false; 144 return false;
164 } 145 }
165 if (XkbGetAutoRepeatRate(display.get(), XkbUseCoreKbd, 146 if (XkbGetAutoRepeatRate(display.get(), XkbUseCoreKbd,
166 &(out_rate->initial_delay_in_ms), 147 &(out_rate->initial_delay_in_ms),
167 &(out_rate->repeat_interval_in_ms)) != True) { 148 &(out_rate->repeat_interval_in_ms)) != True) {
168 out_rate->initial_delay_in_ms = 0; 149 out_rate->initial_delay_in_ms = 0;
169 out_rate->repeat_interval_in_ms = 0; 150 out_rate->repeat_interval_in_ms = 0;
170 return false; 151 return false;
171 } 152 }
172 return true; 153 return true;
173 } 154 }
174 155
175 // Sets the auto-repeat rate of the keyboard, initial delay in ms, and repeat 156 // Sets the auto-repeat rate of the keyboard, initial delay in ms, and repeat
176 // interval in ms. Returns true on success. 157 // interval in ms. Returns true on success.
158 // TODO(yusukes): Call this function in non-UI thread or in an idle callback.
177 bool SetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) { 159 bool SetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) {
178 // TODO(yusukes): write auto tests for the function. 160 // TODO(yusukes): write auto tests for the function.
179 ScopedDisplay display(XOpenDisplay(NULL)); 161 ScopedDisplay display(XOpenDisplay(NULL));
180 if (!display.get()) { 162 if (!display.get()) {
181 return false; 163 return false;
182 } 164 }
183 165
184 DLOG(INFO) << "Set auto-repeat rate to: " 166 DLOG(INFO) << "Set auto-repeat rate to: "
185 << rate.initial_delay_in_ms << " ms delay, " 167 << rate.initial_delay_in_ms << " ms delay, "
186 << rate.repeat_interval_in_ms << " ms interval"; 168 << rate.repeat_interval_in_ms << " ms interval";
187 if (XkbSetAutoRepeatRate(display.get(), XkbUseCoreKbd, 169 if (XkbSetAutoRepeatRate(display.get(), XkbUseCoreKbd,
188 rate.initial_delay_in_ms, 170 rate.initial_delay_in_ms,
189 rate.repeat_interval_in_ms) != True) { 171 rate.repeat_interval_in_ms) != True) {
190 LOG(ERROR) << "Failed to set auto-repeat rate"; 172 LOG(ERROR) << "Failed to set auto-repeat rate";
191 return false; 173 return false;
192 } 174 }
193 return true; 175 return true;
194 } 176 }
195 177
196 private: 178 private:
197 friend struct DefaultSingletonTraits<XKeyboard>; 179 friend struct DefaultSingletonTraits<XKeyboard>;
198 180
199 XKeyboard() : modifier_keys_are_remapped_(false) { 181 XKeyboard() : current_layout_name_(kDefaultLayoutName) {
200 InitializeStringToModifierMap(&string_to_modifier_map_); 182 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
183 chromeos::ModifierKey key = kCustomizableKeys[i];
184 current_modifier_map_.push_back(chromeos::ModifierKeyPair(key, key));
185 }
201 } 186 }
202 ~XKeyboard() { 187 ~XKeyboard() {
203 } 188 }
204 189
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 190 // This function is used by SetLayout() and RemapModifierKeys(). Calls
234 // setxkbmap command if needed, and updates the last_full_layout_name_ cache. 191 // 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 192 // If |use_version| is false, the function does not add "+version(...)" to the
236 // layout name. See http://crosbug.com/6261 for details. 193 // layout name. See http://crosbug.com/6261 for details.
237 bool SetLayoutInternal(const std::string& layout_name, 194 bool SetLayoutInternal(const std::string& layout_name,
238 const chromeos::ModifierMap& modifier_map, 195 const chromeos::ModifierMap& modifier_map,
239 bool use_version) { 196 bool use_version) {
240 const std::string layouts_to_set = chromeos::CreateFullXkbLayoutName( 197 const std::string layouts_to_set = chromeos::CreateFullXkbLayoutName(
241 layout_name, modifier_map, use_version); 198 layout_name, modifier_map, use_version);
242 if (layouts_to_set.empty()) { 199 if (layouts_to_set.empty()) {
243 return false; 200 return false;
244 } 201 }
245 202
246 // Since executing setxkbmap takes more than 200 ms on EeePC, and this 203 const std::string current_layout = chromeos::CreateFullXkbLayoutName(
247 // function is called on every focus-in event, try to reduce the number of 204 current_layout_name_, current_modifier_map_, use_version);
248 // the fork/exec calls. 205 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; 206 DLOG(INFO) << "The requested layout is already set: " << layouts_to_set;
251 return true; 207 return true;
252 } 208 }
253 209
254 // Turn off caps lock if there is no kCapsLockKey in the remapped keys. 210 // Turn off caps lock if there is no kCapsLockKey in the remapped keys.
255 if (!ContainsModifierKeyAsReplacement( 211 if (!ContainsModifierKeyAsReplacement(
256 modifier_map, chromeos::kCapsLockKey)) { 212 modifier_map, chromeos::kCapsLockKey)) {
257 chromeos::SetCapsLockEnabled(false); 213 chromeos::SetCapsLockEnabled(false);
258 } 214 }
259 215
260 gint exit_status = -1; 216 ExecuteSetLayoutCommand(layouts_to_set);
261 const gboolean successful =
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 }
275
276 // Executes 'setxkbmap -layout ...' command. Returns true if execve suceeds.
277 bool ExecuteSetLayoutCommand(const std::string& layouts_to_set,
278 gint* out_exit_status) {
279 *out_exit_status = -1;
280
281 gchar* argv[] = {
282 g_strdup(kSetxkbmapCommand), g_strdup("-layout"),
283 g_strdup(layouts_to_set.c_str()), NULL
284 };
285 GError* error = NULL;
286 const gboolean successful = g_spawn_sync(NULL, argv, NULL,
287 static_cast<GSpawnFlags>(0),
288 NULL, NULL, NULL, NULL,
289 out_exit_status, &error);
290 for (size_t i = 0; argv[i] != NULL; ++i) {
291 g_free(argv[i]);
292 }
293
294 if (!successful) {
295 if (error && error->message) {
296 LOG(ERROR) << "Failed to execute setxkbmap: " << error->message;
297 }
298 g_error_free(error);
299 }
300 return (successful == TRUE);
301 }
302
303 // Executes 'setxkbmap -print' command and parses the output (stdout) from the
304 // command. Returns true if both execve and parsing the output succeed.
305 // On success, it stores a string like "us+chromeos(..)+version(..)+inet(..)"
306 // on |out_command_output|.
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; 217 return true;
348 } 218 }
349 219
350 // The XKB layout name which we set last time like 220 // Executes 'setxkbmap -layout ...' command asynchronously.
351 // "us+chromeos(search_leftcontrol_leftalt)". 221 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
352 std::string last_full_layout_name_; 222 void ExecuteSetLayoutCommand(const std::string& layouts_to_set) {
223 chromeos::ProcessImpl process;
224 process.AddArg(kSetxkbmapCommand);
225 process.AddStringOption("-layout", layouts_to_set);
226 if (!process.Start()) {
227 LOG(ERROR) << "Failed to execute setxkbmap: " << layouts_to_set;
228 return;
229 }
230 // g_child_watch_add is necessary to prevent the process from becoming a
231 // zombie.
232 g_child_watch_add(process.pid(),
233 reinterpret_cast<GChildWatchFunc>(OnSetLayoutFinish),
234 this);
235 process.Release(); // do not kill the setxkbmap process on function exit.
236 }
353 237
354 // A std::map that holds mappings like: "leftcontrol_disabled_leftalt" -> 238 static void OnSetLayoutFinish(GPid pid, gint status, XKeyboard* self) {
355 // { LEFT_CONTROL_KEY, VOID_KEY, LEFT_ALT_KEY }. 239 DLOG(INFO) << "OnSetLayoutFinish: pid=" << pid;
356 chromeos::StringToModifierMap string_to_modifier_map_; 240 }
357 241
358 // True if modifier keys are remapped. 242 // The XKB layout name which we set last time like "us" and "us(dvorak)".
359 bool modifier_keys_are_remapped_; 243 std::string current_layout_name_;
244 // The mapping of modifier keys we set last time.
245 chromeos::ModifierMap current_modifier_map_;
360 246
361 DISALLOW_COPY_AND_ASSIGN(XKeyboard); 247 DISALLOW_COPY_AND_ASSIGN(XKeyboard);
362 }; 248 };
363 249
364 } // namespace 250 } // namespace
365 251
366 namespace chromeos { 252 namespace chromeos {
367 253
368 std::string CreateFullXkbLayoutName(const std::string& layout_name, 254 std::string CreateFullXkbLayoutName(const std::string& layout_name,
369 const ModifierMap& modifier_map, 255 const ModifierMap& modifier_map,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 version.c_str()); 319 version.c_str());
434 320
435 if ((full_xkb_layout_name.substr(0, 3) != "us+") && 321 if ((full_xkb_layout_name.substr(0, 3) != "us+") &&
436 (full_xkb_layout_name.substr(0, 3) != "us(")) { 322 (full_xkb_layout_name.substr(0, 3) != "us(")) {
437 full_xkb_layout_name += ",us"; 323 full_xkb_layout_name += ",us";
438 } 324 }
439 325
440 return full_xkb_layout_name; 326 return full_xkb_layout_name;
441 } 327 }
442 328
443 std::string ExtractLayoutNameFromFullXkbLayoutName( 329 // 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() { 330 bool CapsLockIsEnabled() {
514 ScopedDisplay display(XOpenDisplay(NULL)); 331 ScopedDisplay display(XOpenDisplay(NULL));
515 if (!display.get()) { 332 if (!display.get()) {
516 return false; 333 return false;
517 } 334 }
518 XkbStateRec status; 335 XkbStateRec status;
519 XkbGetState(display.get(), XkbUseCoreKbd, &status); 336 XkbGetState(display.get(), XkbUseCoreKbd, &status);
520 return status.locked_mods & LockMask; 337 return status.locked_mods & LockMask;
521 } 338 }
522 339
340 // TODO(yusukes): Call this function in non-UI thread or in an idle callback.
523 void SetCapsLockEnabled(bool enable_caps_lock) { 341 void SetCapsLockEnabled(bool enable_caps_lock) {
524 ScopedDisplay display(XOpenDisplay(NULL)); 342 ScopedDisplay display(XOpenDisplay(NULL));
525 if (!display.get()) { 343 if (!display.get()) {
526 return; 344 return;
527 } 345 }
528 XkbLockModifiers( 346 XkbLockModifiers(
529 display.get(), XkbUseCoreKbd, LockMask, enable_caps_lock ? LockMask : 0); 347 display.get(), XkbUseCoreKbd, LockMask, enable_caps_lock ? LockMask : 0);
530 } 348 }
531 349
532 bool ContainsModifierKeyAsReplacement( 350 bool ContainsModifierKeyAsReplacement(
(...skipping 15 matching lines...) Expand all
548 extern "C" 366 extern "C"
549 bool ChromeOSSetCurrentKeyboardLayoutByName(const std::string& layout_name) { 367 bool ChromeOSSetCurrentKeyboardLayoutByName(const std::string& layout_name) {
550 return XKeyboard::Get()->SetLayout(layout_name); 368 return XKeyboard::Get()->SetLayout(layout_name);
551 } 369 }
552 370
553 extern "C" 371 extern "C"
554 bool ChromeOSRemapModifierKeys(const chromeos::ModifierMap& modifier_map) { 372 bool ChromeOSRemapModifierKeys(const chromeos::ModifierMap& modifier_map) {
555 return XKeyboard::Get()->RemapModifierKeys(modifier_map); 373 return XKeyboard::Get()->RemapModifierKeys(modifier_map);
556 } 374 }
557 375
376 // TODO(yusukes): Remove this function.
558 extern "C" 377 extern "C"
559 bool ChromeOSGetAutoRepeatEnabled(bool* enabled) { 378 bool ChromeOSGetAutoRepeatEnabled(bool* enabled) {
560 return XKeyboard::Get()->GetAutoRepeatEnabled(enabled); 379 return XKeyboard::Get()->GetAutoRepeatEnabled(enabled);
561 } 380 }
562 381
382 // TODO(yusukes): We can remove this function since the default setting of the
383 // repeat mode is true, and we don't change the default.
563 extern "C" 384 extern "C"
564 bool ChromeOSSetAutoRepeatEnabled(bool enabled) { 385 bool ChromeOSSetAutoRepeatEnabled(bool enabled) {
565 return XKeyboard::Get()->SetAutoRepeatEnabled(enabled); 386 return XKeyboard::Get()->SetAutoRepeatEnabled(enabled);
566 } 387 }
567 388
389 // TODO(yusukes): Remove this function.
568 extern "C" 390 extern "C"
569 bool ChromeOSGetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) { 391 bool ChromeOSGetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
570 return XKeyboard::Get()->GetAutoRepeatRate(out_rate); 392 return XKeyboard::Get()->GetAutoRepeatRate(out_rate);
571 } 393 }
572 394
573 extern "C" 395 extern "C"
574 bool ChromeOSSetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) { 396 bool ChromeOSSetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) {
575 return XKeyboard::Get()->SetAutoRepeatRate(rate); 397 return XKeyboard::Get()->SetAutoRepeatRate(rate);
576 } 398 }
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