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

Side by Side Diff: chrome/browser/chromeos/input_method/xkeyboard.cc

Issue 10383301: Move modifier remapping code from X to Ash (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: reverted ui/base/keycodes/keyboard_code_conversion_x.cc (this was just for debugging) Created 8 years, 7 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/input_method/xkeyboard.h" 5 #include "chrome/browser/chromeos/input_method/xkeyboard.h"
6 6
7 #include <cstdlib> 7 #include <cstdlib>
8 #include <cstring> 8 #include <cstring>
9 #include <queue> 9 #include <queue>
10 #include <set> 10 #include <set>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/chromeos/chromeos_version.h" 13 #include "base/chromeos/chromeos_version.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/process_util.h" 16 #include "base/process_util.h"
17 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/stringprintf.h" 18 #include "base/stringprintf.h"
19 #include "chrome/browser/chromeos/input_method/input_method_util.h" 19 #include "chrome/browser/chromeos/input_method/input_method_util.h"
20 #include "chrome/browser/chromeos/input_method/xkeyboard_data.h"
21 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
22 #include "ui/base/x/x11_util.h" 21 #include "ui/base/x/x11_util.h"
23 22
24 // These includes conflict with base/tracked_objects.h so must come last. 23 // These includes conflict with base/tracked_objects.h so must come last.
25 #include <X11/XKBlib.h> 24 #include <X11/XKBlib.h>
26 #include <X11/Xlib.h> 25 #include <X11/Xlib.h>
27 #include <glib.h> 26 #include <glib.h>
28 27
29 using content::BrowserThread; 28 using content::BrowserThread;
30 29
31 namespace chromeos { 30 namespace chromeos {
32 namespace input_method { 31 namespace input_method {
33 namespace { 32 namespace {
34 33
35 // The default keyboard layout name in the xorg config file. 34 // The default keyboard layout name in the xorg config file.
36 const char kDefaultLayoutName[] = "us"; 35 const char kDefaultLayoutName[] = "us";
37 36
38 // The command we use to set the current XKB layout and modifier key mapping. 37 // The command we use to set the current XKB layout and modifier key mapping.
39 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) 38 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
40 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; 39 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap";
41 40
42 // See the comment at ModifierKey in the .h file.
43 ModifierKey kCustomizableKeys[] = {
44 kSearchKey,
45 kControlKey,
46 kAltKey
47 };
48
49 // A string for obtaining a mask value for Num Lock. 41 // A string for obtaining a mask value for Num Lock.
50 const char kNumLockVirtualModifierString[] = "NumLock"; 42 const char kNumLockVirtualModifierString[] = "NumLock";
51 43
52 class XKeyboardImpl : public XKeyboard { 44 class XKeyboardImpl : public XKeyboard {
53 public: 45 public:
54 explicit XKeyboardImpl(const InputMethodUtil& util); 46 explicit XKeyboardImpl(const InputMethodUtil& util);
55 virtual ~XKeyboardImpl() {} 47 virtual ~XKeyboardImpl() {}
56 48
57 // Overridden from XKeyboard: 49 // Overridden from XKeyboard:
58 virtual bool SetCurrentKeyboardLayoutByName( 50 virtual bool SetCurrentKeyboardLayoutByName(
59 const std::string& layout_name) OVERRIDE; 51 const std::string& layout_name) OVERRIDE;
60 virtual bool RemapModifierKeys(const ModifierMap& modifier_map) OVERRIDE;
61 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE; 52 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE;
62 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE; 53 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE;
63 virtual void SetLockedModifiers( 54 virtual void SetLockedModifiers(
64 ModifierLockStatus new_caps_lock_status, 55 ModifierLockStatus new_caps_lock_status,
65 ModifierLockStatus new_num_lock_status) OVERRIDE; 56 ModifierLockStatus new_num_lock_status) OVERRIDE;
66 virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE; 57 virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE;
67 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE; 58 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE;
68 virtual bool NumLockIsEnabled() OVERRIDE; 59 virtual bool NumLockIsEnabled() OVERRIDE;
69 virtual bool CapsLockIsEnabled() OVERRIDE; 60 virtual bool CapsLockIsEnabled() OVERRIDE;
70 virtual unsigned int GetNumLockMask() OVERRIDE; 61 virtual unsigned int GetNumLockMask() OVERRIDE;
71 virtual void GetLockedModifiers(bool* out_caps_lock_enabled, 62 virtual void GetLockedModifiers(bool* out_caps_lock_enabled,
72 bool* out_num_lock_enabled) OVERRIDE; 63 bool* out_num_lock_enabled) OVERRIDE;
73 virtual std::string CreateFullXkbLayoutName( 64 virtual std::string CreateFullXkbLayoutName(
74 const std::string& layout_name, 65 const std::string& layout_name) OVERRIDE;
75 const ModifierMap& modifire_map) OVERRIDE;
76 66
77 private: 67 private:
78 // This function is used by SetLayout() and RemapModifierKeys(). Calls 68 // This function is used by SetLayout() and RemapModifierKeys(). Calls
79 // setxkbmap command if needed, and updates the last_full_layout_name_ cache. 69 // setxkbmap command if needed, and updates the last_full_layout_name_ cache.
80 bool SetLayoutInternal(const std::string& layout_name, 70 bool SetLayoutInternal(const std::string& layout_name, bool force);
81 const ModifierMap& modifier_map,
82 bool force);
83 71
84 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name 72 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name
85 // in the |execute_queue_|. Do nothing if the queue is empty. 73 // in the |execute_queue_|. Do nothing if the queue is empty.
86 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) 74 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
87 void MaybeExecuteSetLayoutCommand(); 75 void MaybeExecuteSetLayoutCommand();
88 76
89 // Returns true if the XKB layout uses the right Alt key for special purposes
90 // like AltGr.
91 bool KeepRightAlt(const std::string& xkb_layout_name) const;
92
93 // Returns true if the XKB layout uses the CapsLock key for special purposes.
94 // For example, since US Colemak layout uses the key as back space,
95 // KeepCapsLock("us(colemak)") would return true.
96 bool KeepCapsLock(const std::string& xkb_layout_name) const;
97
98 // Returns true if the current thread is the UI thread, or the process is 77 // Returns true if the current thread is the UI thread, or the process is
99 // running on Linux. 78 // running on Linux.
100 bool CurrentlyOnUIThread() const; 79 bool CurrentlyOnUIThread() const;
101 80
102 // Converts |key| to a modifier key name which is used in
103 // /usr/share/X11/xkb/symbols/chromeos.
104 static std::string ModifierKeyToString(ModifierKey key);
105
106 // Called when execve'd setxkbmap process exits. 81 // Called when execve'd setxkbmap process exits.
107 static void OnSetLayoutFinish(pid_t pid, int status, XKeyboardImpl* self); 82 static void OnSetLayoutFinish(pid_t pid, int status, XKeyboardImpl* self);
108 83
109 const bool is_running_on_chrome_os_; 84 const bool is_running_on_chrome_os_;
110 unsigned int num_lock_mask_; 85 unsigned int num_lock_mask_;
111 86
112 // The current Num Lock and Caps Lock status. If true, enabled. 87 // The current Num Lock and Caps Lock status. If true, enabled.
113 bool current_num_lock_status_; 88 bool current_num_lock_status_;
114 bool current_caps_lock_status_; 89 bool current_caps_lock_status_;
115 // The XKB layout name which we set last time like "us" and "us(dvorak)". 90 // The XKB layout name which we set last time like "us" and "us(dvorak)".
116 std::string current_layout_name_; 91 std::string current_layout_name_;
117 // The mapping of modifier keys we set last time.
118 ModifierMap current_modifier_map_;
119 92
120 // A queue for executing setxkbmap one by one. 93 // A queue for executing setxkbmap one by one.
121 std::queue<std::string> execute_queue_; 94 std::queue<std::string> execute_queue_;
122 95
123 std::set<std::string> keep_right_alt_xkb_layout_names_;
124 std::set<std::string> caps_lock_remapped_xkb_layout_names_;
125
126 DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl); 96 DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl);
127 }; 97 };
128 98
129 XKeyboardImpl::XKeyboardImpl(const InputMethodUtil& util) 99 XKeyboardImpl::XKeyboardImpl(const InputMethodUtil& util)
130 : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()) { 100 : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()) {
131 num_lock_mask_ = GetNumLockMask(); 101 num_lock_mask_ = GetNumLockMask();
132 102
133 // web_input_event_aurax11.cc seems to assume that Mod2Mask is always assigned 103 // web_input_event_aurax11.cc seems to assume that Mod2Mask is always assigned
134 // to Num Lock. 104 // to Num Lock.
135 // TODO(yusukes): Check the assumption is really okay. If not, modify the Aura 105 // TODO(yusukes): Check the assumption is really okay. If not, modify the Aura
136 // code, and then remove the CHECK below. 106 // code, and then remove the CHECK below.
137 CHECK(!is_running_on_chrome_os_ || (num_lock_mask_ == Mod2Mask)); 107 CHECK(!is_running_on_chrome_os_ || (num_lock_mask_ == Mod2Mask));
138 GetLockedModifiers(&current_caps_lock_status_, &current_num_lock_status_); 108 GetLockedModifiers(&current_caps_lock_status_, &current_num_lock_status_);
139
140 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
141 ModifierKey key = kCustomizableKeys[i];
142 current_modifier_map_.push_back(ModifierKeyPair(key, key));
143 }
144
145 std::string layout;
146 for (size_t i = 0; i < arraysize(kKeepRightAltInputMethods); ++i) {
147 layout = util.GetKeyboardLayoutName(kKeepRightAltInputMethods[i]);
148 keep_right_alt_xkb_layout_names_.insert(layout);
149 }
150 for (size_t i = 0; i < arraysize(kCapsLockRemapped); ++i) {
151 layout = util.GetKeyboardLayoutName(kCapsLockRemapped[i]);
152 caps_lock_remapped_xkb_layout_names_.insert(layout);
153 }
154 } 109 }
155 110
156 bool XKeyboardImpl::SetLayoutInternal(const std::string& layout_name, 111 bool XKeyboardImpl::SetLayoutInternal(const std::string& layout_name,
157 const ModifierMap& modifier_map,
158 bool force) { 112 bool force) {
159 if (!is_running_on_chrome_os_) { 113 if (!is_running_on_chrome_os_) {
160 // We should not try to change a layout on Linux or inside ui_tests. Just 114 // We should not try to change a layout on Linux or inside ui_tests. Just
161 // return true. 115 // return true.
162 return true; 116 return true;
163 } 117 }
164 118
165 const std::string layout_to_set = CreateFullXkbLayoutName( 119 const std::string layout_to_set = CreateFullXkbLayoutName(layout_name);
166 layout_name, modifier_map); 120 if (layout_to_set.empty())
167 if (layout_to_set.empty()) {
168 return false; 121 return false;
169 }
170 122
171 if (!current_layout_name_.empty()) { 123 if (!current_layout_name_.empty()) {
172 const std::string current_layout = CreateFullXkbLayoutName( 124 const std::string current_layout = CreateFullXkbLayoutName(
173 current_layout_name_, current_modifier_map_); 125 current_layout_name_);
174 if (!force && (current_layout == layout_to_set)) { 126 if (!force && (current_layout == layout_to_set)) {
175 DVLOG(1) << "The requested layout is already set: " << layout_to_set; 127 DVLOG(1) << "The requested layout is already set: " << layout_to_set;
176 return true; 128 return true;
177 } 129 }
178 } 130 }
179 131
180 // Turn off caps lock if there is no kCapsLockKey in the remapped keys.
181 if (!ContainsModifierKeyAsReplacement(modifier_map, kCapsLockKey)) {
182 SetCapsLockEnabled(false);
183 }
184
185 DVLOG(1) << (force ? "Reapply" : "Set") << " layout: " << layout_to_set; 132 DVLOG(1) << (force ? "Reapply" : "Set") << " layout: " << layout_to_set;
186 133
187 const bool start_execution = execute_queue_.empty(); 134 const bool start_execution = execute_queue_.empty();
188 // If no setxkbmap command is in flight (i.e. start_execution is true), 135 // If no setxkbmap command is in flight (i.e. start_execution is true),
189 // start the first one by explicitly calling MaybeExecuteSetLayoutCommand(). 136 // start the first one by explicitly calling MaybeExecuteSetLayoutCommand().
190 // If one or more setxkbmap commands are already in flight, just push the 137 // If one or more setxkbmap commands are already in flight, just push the
191 // layout name to the queue. setxkbmap command for the layout will be called 138 // layout name to the queue. setxkbmap command for the layout will be called
192 // via OnSetLayoutFinish() callback later. 139 // via OnSetLayoutFinish() callback later.
193 execute_queue_.push(layout_to_set); 140 execute_queue_.push(layout_to_set);
194 if (start_execution) { 141 if (start_execution)
195 MaybeExecuteSetLayoutCommand(); 142 MaybeExecuteSetLayoutCommand();
196 } 143
197 return true; 144 return true;
198 } 145 }
199 146
200 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name 147 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name
201 // in the |execute_queue_|. Do nothing if the queue is empty. 148 // in the |execute_queue_|. Do nothing if the queue is empty.
202 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) 149 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
203 void XKeyboardImpl::MaybeExecuteSetLayoutCommand() { 150 void XKeyboardImpl::MaybeExecuteSetLayoutCommand() {
204 if (execute_queue_.empty()) { 151 if (execute_queue_.empty())
205 return; 152 return;
206 }
207 const std::string layout_to_set = execute_queue_.front(); 153 const std::string layout_to_set = execute_queue_.front();
208 154
209 std::vector<std::string> argv; 155 std::vector<std::string> argv;
210 base::ProcessHandle handle = base::kNullProcessHandle; 156 base::ProcessHandle handle = base::kNullProcessHandle;
211 157
212 argv.push_back(kSetxkbmapCommand); 158 argv.push_back(kSetxkbmapCommand);
213 argv.push_back("-layout"); 159 argv.push_back("-layout");
214 argv.push_back(layout_to_set); 160 argv.push_back(layout_to_set);
215 argv.push_back("-synch"); 161 argv.push_back("-synch");
216 162
(...skipping 24 matching lines...) Expand all
241 return caps_lock_enabled; 187 return caps_lock_enabled;
242 } 188 }
243 189
244 unsigned int XKeyboardImpl::GetNumLockMask() { 190 unsigned int XKeyboardImpl::GetNumLockMask() {
245 CHECK(CurrentlyOnUIThread()); 191 CHECK(CurrentlyOnUIThread());
246 static const unsigned int kBadMask = 0; 192 static const unsigned int kBadMask = 0;
247 193
248 unsigned int real_mask = kBadMask; 194 unsigned int real_mask = kBadMask;
249 XkbDescPtr xkb_desc = 195 XkbDescPtr xkb_desc =
250 XkbGetKeyboard(ui::GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd); 196 XkbGetKeyboard(ui::GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd);
251 if (!xkb_desc) { 197 if (!xkb_desc)
252 return kBadMask; 198 return kBadMask;
253 }
254 199
255 if (xkb_desc->dpy && xkb_desc->names && xkb_desc->names->vmods) { 200 if (xkb_desc->dpy && xkb_desc->names && xkb_desc->names->vmods) {
256 const std::string string_to_find(kNumLockVirtualModifierString); 201 const std::string string_to_find(kNumLockVirtualModifierString);
257 for (size_t i = 0; i < XkbNumVirtualMods; ++i) { 202 for (size_t i = 0; i < XkbNumVirtualMods; ++i) {
258 const unsigned int virtual_mod_mask = 1U << i; 203 const unsigned int virtual_mod_mask = 1U << i;
259 ui::XScopedString virtual_mod_str( 204 ui::XScopedString virtual_mod_str(
260 XGetAtomName(xkb_desc->dpy, xkb_desc->names->vmods[i])); 205 XGetAtomName(xkb_desc->dpy, xkb_desc->names->vmods[i]));
261 if (!virtual_mod_str.string()) 206 if (!virtual_mod_str.string())
262 continue; 207 continue;
263 if (string_to_find == virtual_mod_str.string()) { 208 if (string_to_find == virtual_mod_str.string()) {
264 if (!XkbVirtualModsToReal(xkb_desc, virtual_mod_mask, &real_mask)) { 209 if (!XkbVirtualModsToReal(xkb_desc, virtual_mod_mask, &real_mask)) {
265 DVLOG(1) << "XkbVirtualModsToReal failed"; 210 DVLOG(1) << "XkbVirtualModsToReal failed";
266 real_mask = kBadMask; // reset the return value, just in case. 211 real_mask = kBadMask; // reset the return value, just in case.
267 } 212 }
268 break; 213 break;
269 } 214 }
270 } 215 }
271 } 216 }
272 XkbFreeKeyboard(xkb_desc, 0, True /* free all components */); 217 XkbFreeKeyboard(xkb_desc, 0, True /* free all components */);
273 return real_mask; 218 return real_mask;
274 } 219 }
275 220
276 void XKeyboardImpl::GetLockedModifiers(bool* out_caps_lock_enabled, 221 void XKeyboardImpl::GetLockedModifiers(bool* out_caps_lock_enabled,
277 bool* out_num_lock_enabled) { 222 bool* out_num_lock_enabled) {
278 CHECK(CurrentlyOnUIThread()); 223 CHECK(CurrentlyOnUIThread());
279 224
280 if (out_num_lock_enabled && !num_lock_mask_) { 225 if (out_num_lock_enabled && !num_lock_mask_) {
281 DVLOG(1) << "Cannot get locked modifiers. Num Lock mask unknown."; 226 DVLOG(1) << "Cannot get locked modifiers. Num Lock mask unknown.";
282 if (out_caps_lock_enabled) { 227 if (out_caps_lock_enabled)
283 *out_caps_lock_enabled = false; 228 *out_caps_lock_enabled = false;
284 } 229 if (out_num_lock_enabled)
285 if (out_num_lock_enabled) {
286 *out_num_lock_enabled = false; 230 *out_num_lock_enabled = false;
287 }
288 return; 231 return;
289 } 232 }
290 233
291 XkbStateRec status; 234 XkbStateRec status;
292 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status); 235 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status);
293 if (out_caps_lock_enabled) { 236 if (out_caps_lock_enabled)
294 *out_caps_lock_enabled = status.locked_mods & LockMask; 237 *out_caps_lock_enabled = status.locked_mods & LockMask;
295 } 238 if (out_num_lock_enabled)
296 if (out_num_lock_enabled) {
297 *out_num_lock_enabled = status.locked_mods & num_lock_mask_; 239 *out_num_lock_enabled = status.locked_mods & num_lock_mask_;
298 }
299 } 240 }
300 241
301 std::string XKeyboardImpl::CreateFullXkbLayoutName( 242 std::string XKeyboardImpl::CreateFullXkbLayoutName(
302 const std::string& layout_name, 243 const std::string& layout_name) {
303 const ModifierMap& modifier_map) {
304 static const char kValidLayoutNameCharacters[] = 244 static const char kValidLayoutNameCharacters[] =
305 "abcdefghijklmnopqrstuvwxyz0123456789()-_"; 245 "abcdefghijklmnopqrstuvwxyz0123456789()-_";
306 246
307 if (layout_name.empty()) { 247 if (layout_name.empty()) {
308 DVLOG(1) << "Invalid layout_name: " << layout_name; 248 DVLOG(1) << "Invalid layout_name: " << layout_name;
309 return ""; 249 return "";
310 } 250 }
311 251
312 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) != 252 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) !=
313 std::string::npos) { 253 std::string::npos) {
314 DVLOG(1) << "Invalid layout_name: " << layout_name; 254 DVLOG(1) << "Invalid layout_name: " << layout_name;
315 return ""; 255 return "";
316 } 256 }
317 257
318 std::string use_search_key_as_str; 258 // TODO(yusukes): Remove "+chromeos(...)".
319 std::string use_left_control_key_as_str;
320 std::string use_left_alt_key_as_str;
321
322 for (size_t i = 0; i < modifier_map.size(); ++i) {
323 std::string* target = NULL;
324 switch (modifier_map[i].original) {
325 case kSearchKey:
326 target = &use_search_key_as_str;
327 break;
328 case kControlKey:
329 target = &use_left_control_key_as_str;
330 break;
331 case kAltKey:
332 target = &use_left_alt_key_as_str;
333 break;
334 default:
335 break;
336 }
337 if (!target) {
338 DVLOG(1) << "We don't support remaping "
339 << ModifierKeyToString(modifier_map[i].original);
340 return "";
341 }
342 if (!(target->empty())) {
343 DVLOG(1) << ModifierKeyToString(modifier_map[i].original)
344 << " appeared twice";
345 return "";
346 }
347 *target = ModifierKeyToString(modifier_map[i].replacement);
348 }
349
350 if (use_search_key_as_str.empty() ||
351 use_left_control_key_as_str.empty() ||
352 use_left_alt_key_as_str.empty()) {
353 DVLOG(1) << "Incomplete ModifierMap: size=" << modifier_map.size();
354 return "";
355 }
356
357 if (KeepCapsLock(layout_name)) {
358 use_search_key_as_str = ModifierKeyToString(kSearchKey);
359 }
360
361 std::string full_xkb_layout_name = 259 std::string full_xkb_layout_name =
362 base::StringPrintf("%s+chromeos(%s_%s_%s%s)", 260 base::StringPrintf("%s+chromeos(search_leftcontrol_leftalt_keepralt)",
363 layout_name.c_str(), 261 layout_name.c_str());
364 use_search_key_as_str.c_str(),
365 use_left_control_key_as_str.c_str(),
366 use_left_alt_key_as_str.c_str(),
367 (KeepRightAlt(layout_name) ? "_keepralt" : ""));
368 262
369 return full_xkb_layout_name; 263 return full_xkb_layout_name;
370 } 264 }
371 265
372 void XKeyboardImpl::SetLockedModifiers(ModifierLockStatus new_caps_lock_status, 266 void XKeyboardImpl::SetLockedModifiers(ModifierLockStatus new_caps_lock_status,
373 ModifierLockStatus new_num_lock_status) { 267 ModifierLockStatus new_num_lock_status) {
374 CHECK(CurrentlyOnUIThread()); 268 CHECK(CurrentlyOnUIThread());
375 if (!num_lock_mask_) { 269 if (!num_lock_mask_) {
376 DVLOG(1) << "Cannot set locked modifiers. Num Lock mask unknown."; 270 DVLOG(1) << "Cannot set locked modifiers. Num Lock mask unknown.";
377 return; 271 return;
378 } 272 }
379 273
380 unsigned int affect_mask = 0; 274 unsigned int affect_mask = 0;
381 unsigned int value_mask = 0; 275 unsigned int value_mask = 0;
382 if (new_caps_lock_status != kDontChange) { 276 if (new_caps_lock_status != kDontChange) {
383 affect_mask |= LockMask; 277 affect_mask |= LockMask;
384 value_mask |= ((new_caps_lock_status == kEnableLock) ? LockMask : 0); 278 value_mask |= ((new_caps_lock_status == kEnableLock) ? LockMask : 0);
385 current_caps_lock_status_ = (new_caps_lock_status == kEnableLock); 279 current_caps_lock_status_ = (new_caps_lock_status == kEnableLock);
386 } 280 }
387 if (new_num_lock_status != kDontChange) { 281 if (new_num_lock_status != kDontChange) {
388 affect_mask |= num_lock_mask_; 282 affect_mask |= num_lock_mask_;
389 value_mask |= ((new_num_lock_status == kEnableLock) ? num_lock_mask_ : 0); 283 value_mask |= ((new_num_lock_status == kEnableLock) ? num_lock_mask_ : 0);
390 current_num_lock_status_ = (new_num_lock_status == kEnableLock); 284 current_num_lock_status_ = (new_num_lock_status == kEnableLock);
391 } 285 }
392 286
393 if (affect_mask) { 287 if (affect_mask)
394 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, affect_mask, value_mask); 288 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, affect_mask, value_mask);
395 }
396 } 289 }
397 290
398 void XKeyboardImpl::SetNumLockEnabled(bool enable_num_lock) { 291 void XKeyboardImpl::SetNumLockEnabled(bool enable_num_lock) {
399 SetLockedModifiers( 292 SetLockedModifiers(
400 kDontChange, enable_num_lock ? kEnableLock : kDisableLock); 293 kDontChange, enable_num_lock ? kEnableLock : kDisableLock);
401 } 294 }
402 295
403 void XKeyboardImpl::SetCapsLockEnabled(bool enable_caps_lock) { 296 void XKeyboardImpl::SetCapsLockEnabled(bool enable_caps_lock) {
404 SetLockedModifiers( 297 SetLockedModifiers(
405 enable_caps_lock ? kEnableLock : kDisableLock, kDontChange); 298 enable_caps_lock ? kEnableLock : kDisableLock, kDontChange);
406 } 299 }
407 300
408 bool XKeyboardImpl::SetCurrentKeyboardLayoutByName( 301 bool XKeyboardImpl::SetCurrentKeyboardLayoutByName(
409 const std::string& layout_name) { 302 const std::string& layout_name) {
410 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) { 303 if (SetLayoutInternal(layout_name, false)) {
411 current_layout_name_ = layout_name; 304 current_layout_name_ = layout_name;
412 return true; 305 return true;
413 } 306 }
414 return false; 307 return false;
415 } 308 }
416 309
417 bool XKeyboardImpl::ReapplyCurrentKeyboardLayout() { 310 bool XKeyboardImpl::ReapplyCurrentKeyboardLayout() {
418 if (current_layout_name_.empty()) { 311 if (current_layout_name_.empty()) {
419 DVLOG(1) << "Can't reapply XKB layout: layout unknown"; 312 DVLOG(1) << "Can't reapply XKB layout: layout unknown";
420 return false; 313 return false;
421 } 314 }
422 return SetLayoutInternal( 315 return SetLayoutInternal(current_layout_name_, true /* force */);
423 current_layout_name_, current_modifier_map_, true /* force */);
424 } 316 }
425 317
426 void XKeyboardImpl::ReapplyCurrentModifierLockStatus() { 318 void XKeyboardImpl::ReapplyCurrentModifierLockStatus() {
427 SetLockedModifiers(current_caps_lock_status_ ? kEnableLock : kDisableLock, 319 SetLockedModifiers(current_caps_lock_status_ ? kEnableLock : kDisableLock,
428 current_num_lock_status_ ? kEnableLock : kDisableLock); 320 current_num_lock_status_ ? kEnableLock : kDisableLock);
429 } 321 }
430 322
431 bool XKeyboardImpl::RemapModifierKeys(const ModifierMap& modifier_map) {
432 const std::string layout_name = current_layout_name_.empty() ?
433 kDefaultLayoutName : current_layout_name_;
434 if (SetLayoutInternal(layout_name, modifier_map, false)) {
435 current_layout_name_ = layout_name;
436 current_modifier_map_ = modifier_map;
437 return true;
438 }
439 return false;
440 }
441
442 bool XKeyboardImpl::KeepRightAlt(const std::string& xkb_layout_name) const {
443 return keep_right_alt_xkb_layout_names_.count(xkb_layout_name) > 0;
444 }
445
446 bool XKeyboardImpl::KeepCapsLock(const std::string& xkb_layout_name) const {
447 return caps_lock_remapped_xkb_layout_names_.count(xkb_layout_name) > 0;
448 }
449
450 bool XKeyboardImpl::CurrentlyOnUIThread() const { 323 bool XKeyboardImpl::CurrentlyOnUIThread() const {
451 // It seems that the tot Chrome (as of Mar 7 2012) does not allow browser 324 // It seems that the tot Chrome (as of Mar 7 2012) does not allow browser
452 // tests to call BrowserThread::CurrentlyOn(). It ends up a CHECK failure: 325 // tests to call BrowserThread::CurrentlyOn(). It ends up a CHECK failure:
453 // FATAL:sequenced_worker_pool.cc 326 // FATAL:sequenced_worker_pool.cc
454 // Check failed: constructor_message_loop_.get(). 327 // Check failed: constructor_message_loop_.get().
455 // For now, just allow unit/browser tests to call any functions in this class. 328 // For now, just allow unit/browser tests to call any functions in this class.
456 // TODO(yusukes): Stop special-casing browser_tests and remove this function. 329 // TODO(yusukes): Stop special-casing browser_tests and remove this function.
457 if (!is_running_on_chrome_os_) { 330 if (!is_running_on_chrome_os_)
458 return true; 331 return true;
459 }
460 return BrowserThread::CurrentlyOn(BrowserThread::UI); 332 return BrowserThread::CurrentlyOn(BrowserThread::UI);
461 } 333 }
462 334
463 // static 335 // static
464 std::string XKeyboardImpl::ModifierKeyToString(ModifierKey key) {
465 switch (key) {
466 case kSearchKey:
467 return "search";
468 case kControlKey:
469 return "leftcontrol";
470 case kAltKey:
471 return "leftalt";
472 case kVoidKey:
473 return "disabled";
474 case kCapsLockKey:
475 return "capslock";
476 case kNumModifierKeys:
477 break;
478 }
479 return "";
480 }
481
482 // static
483 void XKeyboardImpl::OnSetLayoutFinish(pid_t pid, 336 void XKeyboardImpl::OnSetLayoutFinish(pid_t pid,
484 int status, 337 int status,
485 XKeyboardImpl* self) { 338 XKeyboardImpl* self) {
486 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 339 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
487 DVLOG(1) << "OnSetLayoutFinish: pid=" << pid; 340 DVLOG(1) << "OnSetLayoutFinish: pid=" << pid;
488 if (self->execute_queue_.empty()) { 341 if (self->execute_queue_.empty()) {
489 DVLOG(1) << "OnSetLayoutFinish: execute_queue_ is empty. " 342 DVLOG(1) << "OnSetLayoutFinish: execute_queue_ is empty. "
490 << "base::LaunchProcess failed? pid=" << pid; 343 << "base::LaunchProcess failed? pid=" << pid;
491 return; 344 return;
492 } 345 }
493 self->execute_queue_.pop(); 346 self->execute_queue_.pop();
494 self->MaybeExecuteSetLayoutCommand(); 347 self->MaybeExecuteSetLayoutCommand();
495 } 348 }
496 349
497 } // namespace 350 } // namespace
498 351
499 // static 352 // static
500 bool XKeyboard::SetAutoRepeatEnabled(bool enabled) { 353 bool XKeyboard::SetAutoRepeatEnabled(bool enabled) {
501 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 354 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
502 if (enabled) { 355 if (enabled)
503 XAutoRepeatOn(ui::GetXDisplay()); 356 XAutoRepeatOn(ui::GetXDisplay());
504 } else { 357 else
505 XAutoRepeatOff(ui::GetXDisplay()); 358 XAutoRepeatOff(ui::GetXDisplay());
506 }
507 DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); 359 DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
508 return true; 360 return true;
509 } 361 }
510 362
511 // static 363 // static
512 bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) { 364 bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) {
513 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 365 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
514 DVLOG(1) << "Set auto-repeat rate to: " 366 DVLOG(1) << "Set auto-repeat rate to: "
515 << rate.initial_delay_in_ms << " ms delay, " 367 << rate.initial_delay_in_ms << " ms delay, "
516 << rate.repeat_interval_in_ms << " ms interval"; 368 << rate.repeat_interval_in_ms << " ms interval";
(...skipping 14 matching lines...) Expand all
531 } 383 }
532 384
533 // static 385 // static
534 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) { 386 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) {
535 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd, 387 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
536 &(out_rate->initial_delay_in_ms), 388 &(out_rate->initial_delay_in_ms),
537 &(out_rate->repeat_interval_in_ms)) == True; 389 &(out_rate->repeat_interval_in_ms)) == True;
538 } 390 }
539 391
540 // static 392 // static
541 bool XKeyboard::ContainsModifierKeyAsReplacement(
542 const ModifierMap& modifier_map,
543 ModifierKey key) {
544 for (size_t i = 0; i < modifier_map.size(); ++i) {
545 if (modifier_map[i].replacement == key) {
546 return true;
547 }
548 }
549 return false;
550 }
551
552 // static
553 XKeyboard* XKeyboard::Create(const InputMethodUtil& util) { 393 XKeyboard* XKeyboard::Create(const InputMethodUtil& util) {
554 return new XKeyboardImpl(util); 394 return new XKeyboardImpl(util);
555 } 395 }
556 396
557 } // namespace input_method 397 } // namespace input_method
558 } // namespace chromeos 398 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/input_method/xkeyboard.h ('k') | chrome/browser/chromeos/input_method/xkeyboard_data.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698