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

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

Issue 9264004: Make almost all public functions in XKeyboard pure virtual (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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>
8 #include <cstring>
7 #include <queue> 9 #include <queue>
8 #include <set> 10 #include <set>
9 #include <string>
10 #include <utility> 11 #include <utility>
11 12
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "base/logging.h" 13 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
17 #include "base/process_util.h" 15 #include "base/process_util.h"
18 #include "base/string_util.h" 16 #include "base/string_util.h"
19 #include "base/stringprintf.h" 17 #include "base/stringprintf.h"
20 #include "chrome/browser/chromeos/input_method/input_method_util.h" 18 #include "chrome/browser/chromeos/input_method/input_method_util.h"
21 #include "chrome/browser/chromeos/system/runtime_environment.h" 19 #include "chrome/browser/chromeos/system/runtime_environment.h"
22 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
23 #include "ui/base/x/x11_util.h" 21 #include "ui/base/x/x11_util.h"
24 22
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 92
95 // These are the overlay names with caps lock remapped 93 // These are the overlay names with caps lock remapped
96 const char* kCapsLockRemapped[] = { 94 const char* kCapsLockRemapped[] = {
97 "xkb:de:neo:ger", 95 "xkb:de:neo:ger",
98 "xkb:us:colemak:eng", 96 "xkb:us:colemak:eng",
99 }; 97 };
100 98
101 // A string for obtaining a mask value for Num Lock. 99 // A string for obtaining a mask value for Num Lock.
102 const char kNumLockVirtualModifierString[] = "NumLock"; 100 const char kNumLockVirtualModifierString[] = "NumLock";
103 101
104 } // namespace 102 class XKeyboardImpl : public XKeyboard {
103 public:
104 explicit XKeyboardImpl(const InputMethodUtil& util);
105 virtual ~XKeyboardImpl() {}
105 106
106 XKeyboard::XKeyboard(const InputMethodUtil& util) 107 // Overridden from XKeyboard:
108 virtual bool SetCurrentKeyboardLayoutByName(
109 const std::string& layout_name) OVERRIDE;
110 virtual bool RemapModifierKeys(const ModifierMap& modifier_map) OVERRIDE;
111 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE;
112 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE;
113 virtual void SetLockedModifiers(
114 ModifierLockStatus new_caps_lock_status,
115 ModifierLockStatus new_num_lock_status) OVERRIDE;
116 virtual void SetNumLockEnabled(bool enable_num_lock) OVERRIDE;
117 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE;
118 virtual bool NumLockIsEnabled() OVERRIDE;
119 virtual bool CapsLockIsEnabled() OVERRIDE;
120 virtual unsigned int GetNumLockMask() OVERRIDE;
121 virtual void GetLockedModifiers(bool* out_caps_lock_enabled,
122 bool* out_num_lock_enabled) OVERRIDE;
123 virtual std::string CreateFullXkbLayoutName(
124 const std::string& layout_name,
125 const ModifierMap& modifire_map) OVERRIDE;
126
127 private:
128 // This function is used by SetLayout() and RemapModifierKeys(). Calls
129 // setxkbmap command if needed, and updates the last_full_layout_name_ cache.
130 bool SetLayoutInternal(const std::string& layout_name,
131 const ModifierMap& modifier_map,
132 bool force);
133
134 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name
135 // in the |execute_queue_|. Do nothing if the queue is empty.
136 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
137 void MaybeExecuteSetLayoutCommand();
138
139 // Returns true if the XKB layout uses the right Alt key for special purposes
140 // like AltGr.
141 bool KeepRightAlt(const std::string& xkb_layout_name) const;
142
143 // Returns true if the XKB layout uses the CapsLock key for special purposes.
144 // For example, since US Colemak layout uses the key as back space,
145 // KeepCapsLock("us(colemak)") would return true.
146 bool KeepCapsLock(const std::string& xkb_layout_name) const;
147
148 // Converts |key| to a modifier key name which is used in
149 // /usr/share/X11/xkb/symbols/chromeos.
150 static std::string ModifierKeyToString(ModifierKey key);
151
152 // Called when execve'd setxkbmap process exits.
153 static void OnSetLayoutFinish(pid_t pid, int status, XKeyboardImpl* self);
154
155 const bool is_running_on_chrome_os_;
156 unsigned int num_lock_mask_;
157
158 // The current Num Lock and Caps Lock status. If true, enabled.
159 bool current_num_lock_status_;
160 bool current_caps_lock_status_;
161 // The XKB layout name which we set last time like "us" and "us(dvorak)".
162 std::string current_layout_name_;
163 // The mapping of modifier keys we set last time.
164 ModifierMap current_modifier_map_;
165
166 // A queue for executing setxkbmap one by one.
167 std::queue<std::string> execute_queue_;
168
169 std::set<std::string> keep_right_alt_xkb_layout_names_;
170 std::set<std::string> caps_lock_remapped_xkb_layout_names_;
171
172 DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl);
173 };
174
175 XKeyboardImpl::XKeyboardImpl(const InputMethodUtil& util)
107 : is_running_on_chrome_os_( 176 : is_running_on_chrome_os_(
108 system::runtime_environment::IsRunningOnChromeOS()) { 177 system::runtime_environment::IsRunningOnChromeOS()) {
109 num_lock_mask_ = GetNumLockMask(); 178 num_lock_mask_ = GetNumLockMask();
110 179
111 #if defined(USE_AURA) 180 #if defined(USE_AURA)
112 // web_input_event_aurax11.cc seems to assume that Mod2Mask is always assigned 181 // web_input_event_aurax11.cc seems to assume that Mod2Mask is always assigned
113 // to Num Lock. 182 // to Num Lock.
114 // TODO(yusukes): Check the assumption is really okay. If not, modify the Aura 183 // TODO(yusukes): Check the assumption is really okay. If not, modify the Aura
115 // code, and then remove the CHECK below. 184 // code, and then remove the CHECK below.
116 CHECK(!is_running_on_chrome_os_ || (num_lock_mask_ == Mod2Mask)); 185 CHECK(!is_running_on_chrome_os_ || (num_lock_mask_ == Mod2Mask));
117 #endif 186 #endif
118 187
119 GetLockedModifiers( 188 GetLockedModifiers(&current_caps_lock_status_, &current_num_lock_status_);
120 num_lock_mask_, &current_caps_lock_status_, &current_num_lock_status_);
121 189
122 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) { 190 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
123 ModifierKey key = kCustomizableKeys[i]; 191 ModifierKey key = kCustomizableKeys[i];
124 current_modifier_map_.push_back(ModifierKeyPair(key, key)); 192 current_modifier_map_.push_back(ModifierKeyPair(key, key));
125 } 193 }
126 194
127 std::string layout; 195 std::string layout;
128 for (size_t i = 0; i < arraysize(kKeepRightAltInputMethods); ++i) { 196 for (size_t i = 0; i < arraysize(kKeepRightAltInputMethods); ++i) {
129 layout = util.GetKeyboardLayoutName(kKeepRightAltInputMethods[i]); 197 layout = util.GetKeyboardLayoutName(kKeepRightAltInputMethods[i]);
130 // The empty check is necessary since USE_VIRTUAL_KEYBOARD build does not 198 // The empty check is necessary since USE_VIRTUAL_KEYBOARD build does not
131 // support some of the kKeepRightAltInputMethods elements. For example, 199 // support some of the kKeepRightAltInputMethods elements. For example,
132 // when USE_VIRTUAL_KEYBOARD is defined, 200 // when USE_VIRTUAL_KEYBOARD is defined,
133 // util.GetKeyboardLayoutName("xkb:us:intl:eng") would return "". 201 // util.GetKeyboardLayoutName("xkb:us:intl:eng") would return "".
134 if (!layout.empty()) { 202 if (!layout.empty()) {
135 keep_right_alt_xkb_layout_names_.insert(layout); 203 keep_right_alt_xkb_layout_names_.insert(layout);
136 } 204 }
137 } 205 }
138 for (size_t i = 0; i < arraysize(kCapsLockRemapped); ++i) { 206 for (size_t i = 0; i < arraysize(kCapsLockRemapped); ++i) {
139 layout = util.GetKeyboardLayoutName(kCapsLockRemapped[i]); 207 layout = util.GetKeyboardLayoutName(kCapsLockRemapped[i]);
140 // The empty check is for USE_VIRTUAL_KEYBOARD build. See above. 208 // The empty check is for USE_VIRTUAL_KEYBOARD build. See above.
141 if (!layout.empty()) { 209 if (!layout.empty()) {
142 caps_lock_remapped_xkb_layout_names_.insert(layout); 210 caps_lock_remapped_xkb_layout_names_.insert(layout);
143 } 211 }
144 } 212 }
145 } 213 }
146 214
147 XKeyboard::~XKeyboard() { 215 bool XKeyboardImpl::SetLayoutInternal(const std::string& layout_name,
148 } 216 const ModifierMap& modifier_map,
149 217 bool force) {
150 // static
151 unsigned int XKeyboard::GetNumLockMask() {
152 static const unsigned int kBadMask = 0;
153
154 unsigned int real_mask = kBadMask;
155 XkbDescPtr xkb_desc =
156 XkbGetKeyboard(ui::GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd);
157 if (!xkb_desc) {
158 return kBadMask;
159 }
160
161 if (xkb_desc->dpy && xkb_desc->names && xkb_desc->names->vmods) {
162 const std::string string_to_find(kNumLockVirtualModifierString);
163 for (size_t i = 0; i < XkbNumVirtualMods; ++i) {
164 const unsigned int virtual_mod_mask = 1U << i;
165 char* virtual_mod_str =
166 XGetAtomName(xkb_desc->dpy, xkb_desc->names->vmods[i]);
167 if (!virtual_mod_str) {
168 continue;
169 }
170 if (string_to_find == virtual_mod_str) {
171 if (!XkbVirtualModsToReal(xkb_desc, virtual_mod_mask, &real_mask)) {
172 LOG(ERROR) << "XkbVirtualModsToReal failed";
173 real_mask = kBadMask; // reset the return value, just in case.
174 }
175 XFree(virtual_mod_str);
176 break;
177 }
178 XFree(virtual_mod_str);
179 }
180 }
181 XkbFreeKeyboard(xkb_desc, 0, True /* free all components */);
182 return real_mask;
183 }
184
185 bool XKeyboard::SetLayoutInternal(const std::string& layout_name,
186 const ModifierMap& modifier_map,
187 bool force) {
188 if (!is_running_on_chrome_os_) { 218 if (!is_running_on_chrome_os_) {
189 // We should not try to change a layout on Linux or inside ui_tests. Just 219 // We should not try to change a layout on Linux or inside ui_tests. Just
190 // return true. 220 // return true.
191 return true; 221 return true;
192 } 222 }
193 223
194 const std::string layout_to_set = CreateFullXkbLayoutName( 224 const std::string layout_to_set = CreateFullXkbLayoutName(
195 layout_name, modifier_map); 225 layout_name, modifier_map);
196 if (layout_to_set.empty()) { 226 if (layout_to_set.empty()) {
197 return false; 227 return false;
(...skipping 24 matching lines...) Expand all
222 execute_queue_.push(layout_to_set); 252 execute_queue_.push(layout_to_set);
223 if (start_execution) { 253 if (start_execution) {
224 MaybeExecuteSetLayoutCommand(); 254 MaybeExecuteSetLayoutCommand();
225 } 255 }
226 return true; 256 return true;
227 } 257 }
228 258
229 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name 259 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name
230 // in the |execute_queue_|. Do nothing if the queue is empty. 260 // in the |execute_queue_|. Do nothing if the queue is empty.
231 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) 261 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
232 void XKeyboard::MaybeExecuteSetLayoutCommand() { 262 void XKeyboardImpl::MaybeExecuteSetLayoutCommand() {
233 if (execute_queue_.empty()) { 263 if (execute_queue_.empty()) {
234 return; 264 return;
235 } 265 }
236 const std::string layout_to_set = execute_queue_.front(); 266 const std::string layout_to_set = execute_queue_.front();
237 267
238 std::vector<std::string> argv; 268 std::vector<std::string> argv;
239 base::ProcessHandle handle = base::kNullProcessHandle; 269 base::ProcessHandle handle = base::kNullProcessHandle;
240 270
241 argv.push_back(kSetxkbmapCommand); 271 argv.push_back(kSetxkbmapCommand);
242 argv.push_back("-layout"); 272 argv.push_back("-layout");
243 argv.push_back(layout_to_set); 273 argv.push_back(layout_to_set);
244 argv.push_back("-synch"); 274 argv.push_back("-synch");
245 275
246 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) { 276 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) {
247 LOG(ERROR) << "Failed to execute setxkbmap: " << layout_to_set; 277 LOG(ERROR) << "Failed to execute setxkbmap: " << layout_to_set;
248 execute_queue_ = std::queue<std::string>(); // clear the queue. 278 execute_queue_ = std::queue<std::string>(); // clear the queue.
249 return; 279 return;
250 } 280 }
251 281
252 // g_child_watch_add is necessary to prevent the process from becoming a 282 // g_child_watch_add is necessary to prevent the process from becoming a
253 // zombie. 283 // zombie.
254 const base::ProcessId pid = base::GetProcId(handle); 284 const base::ProcessId pid = base::GetProcId(handle);
255 g_child_watch_add(pid, 285 g_child_watch_add(pid,
256 reinterpret_cast<GChildWatchFunc>(OnSetLayoutFinish), 286 reinterpret_cast<GChildWatchFunc>(OnSetLayoutFinish),
257 this); 287 this);
258 VLOG(1) << "ExecuteSetLayoutCommand: " << layout_to_set << ": pid=" << pid; 288 VLOG(1) << "ExecuteSetLayoutCommand: " << layout_to_set << ": pid=" << pid;
259 } 289 }
260 290
261 // static 291 bool XKeyboardImpl::NumLockIsEnabled() {
262 void XKeyboard::OnSetLayoutFinish(pid_t pid, int status, XKeyboard* self) { 292 bool num_lock_enabled = false;
263 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 293 GetLockedModifiers(NULL /* Caps Lock */, &num_lock_enabled);
264 VLOG(1) << "OnSetLayoutFinish: pid=" << pid; 294 return num_lock_enabled;
265 if (self->execute_queue_.empty()) { 295 }
266 LOG(ERROR) << "OnSetLayoutFinish: execute_queue_ is empty. " 296
267 << "base::LaunchProcess failed? pid=" << pid; 297 bool XKeyboardImpl::CapsLockIsEnabled() {
298 bool caps_lock_enabled = false;
299 GetLockedModifiers(&caps_lock_enabled, NULL /* Num Lock */);
300 return caps_lock_enabled;
301 }
302
303 unsigned int XKeyboardImpl::GetNumLockMask() {
304 static const unsigned int kBadMask = 0;
305
306 unsigned int real_mask = kBadMask;
307 XkbDescPtr xkb_desc =
308 XkbGetKeyboard(ui::GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd);
309 if (!xkb_desc) {
310 return kBadMask;
311 }
312
313 if (xkb_desc->dpy && xkb_desc->names && xkb_desc->names->vmods) {
314 const std::string string_to_find(kNumLockVirtualModifierString);
315 for (size_t i = 0; i < XkbNumVirtualMods; ++i) {
316 const unsigned int virtual_mod_mask = 1U << i;
317 char* virtual_mod_str =
318 XGetAtomName(xkb_desc->dpy, xkb_desc->names->vmods[i]);
319 if (!virtual_mod_str) {
320 continue;
321 }
322 if (string_to_find == virtual_mod_str) {
323 if (!XkbVirtualModsToReal(xkb_desc, virtual_mod_mask, &real_mask)) {
324 LOG(ERROR) << "XkbVirtualModsToReal failed";
325 real_mask = kBadMask; // reset the return value, just in case.
326 }
327 XFree(virtual_mod_str);
328 break;
329 }
330 XFree(virtual_mod_str);
331 }
332 }
333 XkbFreeKeyboard(xkb_desc, 0, True /* free all components */);
334 return real_mask;
335 }
336
337 void XKeyboardImpl::GetLockedModifiers(bool* out_caps_lock_enabled,
338 bool* out_num_lock_enabled) {
339 // For now, don't call CHECK() here to make
340 // TabRestoreServiceTest.DontRestorePrintPreviewTab test happy.
341 // TODO(yusukes): Fix the test, then fix the if(!BrowserThread...) line below.
342 // CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
343
344 if (!BrowserThread::CurrentlyOn(BrowserThread::UI) ||
345 (out_num_lock_enabled && !num_lock_mask_)) {
346 LOG(ERROR) << "Cannot get locked modifiers.";
347 if (out_caps_lock_enabled) {
348 *out_caps_lock_enabled = false;
349 }
350 if (out_num_lock_enabled) {
351 *out_num_lock_enabled = false;
352 }
268 return; 353 return;
269 } 354 }
270 self->execute_queue_.pop(); 355
271 self->MaybeExecuteSetLayoutCommand(); 356 XkbStateRec status;
357 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status);
358 if (out_caps_lock_enabled) {
359 *out_caps_lock_enabled = status.locked_mods & LockMask;
360 }
361 if (out_num_lock_enabled) {
362 *out_num_lock_enabled = status.locked_mods & num_lock_mask_;
363 }
272 } 364 }
273 365
274 std::string XKeyboard::CreateFullXkbLayoutName( 366 std::string XKeyboardImpl::CreateFullXkbLayoutName(
275 const std::string& layout_name, const ModifierMap& modifier_map) { 367 const std::string& layout_name,
368 const ModifierMap& modifier_map) {
276 static const char kValidLayoutNameCharacters[] = 369 static const char kValidLayoutNameCharacters[] =
277 "abcdefghijklmnopqrstuvwxyz0123456789()-_"; 370 "abcdefghijklmnopqrstuvwxyz0123456789()-_";
278 371
279 if (layout_name.empty()) { 372 if (layout_name.empty()) {
280 LOG(ERROR) << "Invalid layout_name: " << layout_name; 373 LOG(ERROR) << "Invalid layout_name: " << layout_name;
281 return ""; 374 return "";
282 } 375 }
283 376
284 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) != 377 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) !=
285 std::string::npos) { 378 std::string::npos) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 (KeepRightAlt(layout_name) ? "_keepralt" : "")); 432 (KeepRightAlt(layout_name) ? "_keepralt" : ""));
340 433
341 if ((full_xkb_layout_name.substr(0, 3) != "us+") && 434 if ((full_xkb_layout_name.substr(0, 3) != "us+") &&
342 (full_xkb_layout_name.substr(0, 3) != "us(")) { 435 (full_xkb_layout_name.substr(0, 3) != "us(")) {
343 full_xkb_layout_name += ",us"; 436 full_xkb_layout_name += ",us";
344 } 437 }
345 438
346 return full_xkb_layout_name; 439 return full_xkb_layout_name;
347 } 440 }
348 441
349 // static 442 void XKeyboardImpl::SetLockedModifiers(ModifierLockStatus new_caps_lock_status,
350 bool XKeyboard::SetAutoRepeatEnabled(bool enabled) { 443 ModifierLockStatus new_num_lock_status) {
351 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
352 if (enabled) {
353 XAutoRepeatOn(ui::GetXDisplay());
354 } else {
355 XAutoRepeatOff(ui::GetXDisplay());
356 }
357 DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
358 return true;
359 }
360
361 // static
362 bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) {
363 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
364 DLOG(INFO) << "Set auto-repeat rate to: "
365 << rate.initial_delay_in_ms << " ms delay, "
366 << rate.repeat_interval_in_ms << " ms interval";
367 if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
368 rate.initial_delay_in_ms,
369 rate.repeat_interval_in_ms) != True) {
370 LOG(ERROR) << "Failed to set auto-repeat rate";
371 return false;
372 }
373 return true;
374 }
375
376 // static
377 bool XKeyboard::GetAutoRepeatEnabled() {
378 XKeyboardState state = {};
379 XGetKeyboardControl(ui::GetXDisplay(), &state);
380 return state.global_auto_repeat != AutoRepeatModeOff;
381 }
382
383 // static
384 bool XKeyboard::GetAutoRepeatRate(AutoRepeatRate* out_rate) {
385 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
386 &(out_rate->initial_delay_in_ms),
387 &(out_rate->repeat_interval_in_ms)) == True;
388 }
389
390 void XKeyboard::SetLockedModifiers(ModifierLockStatus new_caps_lock_status,
391 ModifierLockStatus new_num_lock_status) {
392 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 444 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
393 if (!num_lock_mask_) { 445 if (!num_lock_mask_) {
394 LOG(ERROR) << "Cannot set locked modifiers. Num Lock mask unknown."; 446 LOG(ERROR) << "Cannot set locked modifiers. Num Lock mask unknown.";
395 return; 447 return;
396 } 448 }
397 449
398 unsigned int affect_mask = 0; 450 unsigned int affect_mask = 0;
399 unsigned int value_mask = 0; 451 unsigned int value_mask = 0;
400 if (new_caps_lock_status != kDontChange) { 452 if (new_caps_lock_status != kDontChange) {
401 affect_mask |= LockMask; 453 affect_mask |= LockMask;
402 value_mask |= ((new_caps_lock_status == kEnableLock) ? LockMask : 0); 454 value_mask |= ((new_caps_lock_status == kEnableLock) ? LockMask : 0);
403 current_caps_lock_status_ = (new_caps_lock_status == kEnableLock); 455 current_caps_lock_status_ = (new_caps_lock_status == kEnableLock);
404 } 456 }
405 if (new_num_lock_status != kDontChange) { 457 if (new_num_lock_status != kDontChange) {
406 affect_mask |= num_lock_mask_; 458 affect_mask |= num_lock_mask_;
407 value_mask |= ((new_num_lock_status == kEnableLock) ? num_lock_mask_ : 0); 459 value_mask |= ((new_num_lock_status == kEnableLock) ? num_lock_mask_ : 0);
408 current_num_lock_status_ = (new_num_lock_status == kEnableLock); 460 current_num_lock_status_ = (new_num_lock_status == kEnableLock);
409 } 461 }
410 462
411 if (affect_mask) { 463 if (affect_mask) {
412 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, affect_mask, value_mask); 464 XkbLockModifiers(ui::GetXDisplay(), XkbUseCoreKbd, affect_mask, value_mask);
413 } 465 }
414 } 466 }
415 467
416 void XKeyboard::SetNumLockEnabled(bool enable_num_lock) { 468 void XKeyboardImpl::SetNumLockEnabled(bool enable_num_lock) {
417 SetLockedModifiers( 469 SetLockedModifiers(
418 kDontChange, enable_num_lock ? kEnableLock : kDisableLock); 470 kDontChange, enable_num_lock ? kEnableLock : kDisableLock);
419 } 471 }
420 472
421 void XKeyboard::SetCapsLockEnabled(bool enable_caps_lock) { 473 void XKeyboardImpl::SetCapsLockEnabled(bool enable_caps_lock) {
422 SetLockedModifiers( 474 SetLockedModifiers(
423 enable_caps_lock ? kEnableLock : kDisableLock, kDontChange); 475 enable_caps_lock ? kEnableLock : kDisableLock, kDontChange);
424 } 476 }
425 477
426 // static 478 bool XKeyboardImpl::SetCurrentKeyboardLayoutByName(
427 void XKeyboard::GetLockedModifiers(unsigned int num_lock_mask, 479 const std::string& layout_name) {
428 bool* out_caps_lock_enabled,
429 bool* out_num_lock_enabled) {
430 // For now, don't call CHECK() here to make
431 // TabRestoreServiceTest.DontRestorePrintPreviewTab test happy.
432 // TODO(yusukes): Fix the test, then fix the if(!BrowserThread...) line below.
433 // CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
434
435 if (!BrowserThread::CurrentlyOn(BrowserThread::UI) ||
436 (out_num_lock_enabled && !num_lock_mask)) {
437 LOG(ERROR) << "Cannot get locked modifiers.";
438 if (out_caps_lock_enabled) {
439 *out_caps_lock_enabled = false;
440 }
441 if (out_num_lock_enabled) {
442 *out_num_lock_enabled = false;
443 }
444 return;
445 }
446
447 XkbStateRec status;
448 XkbGetState(ui::GetXDisplay(), XkbUseCoreKbd, &status);
449 if (out_caps_lock_enabled) {
450 *out_caps_lock_enabled = status.locked_mods & LockMask;
451 }
452 if (out_num_lock_enabled) {
453 *out_num_lock_enabled = status.locked_mods & num_lock_mask;
454 }
455 }
456
457 // static
458 bool XKeyboard::NumLockIsEnabled(unsigned int num_lock_mask) {
459 bool num_lock_enabled = false;
460 GetLockedModifiers(num_lock_mask, NULL /* Caps Lock */, &num_lock_enabled);
461 return num_lock_enabled;
462 }
463
464 // static
465 bool XKeyboard::CapsLockIsEnabled() {
466 bool caps_lock_enabled = false;
467 GetLockedModifiers(0, &caps_lock_enabled, NULL /* Num Lock */);
468 return caps_lock_enabled;
469 }
470
471 // static
472 bool XKeyboard::ContainsModifierKeyAsReplacement(
473 const ModifierMap& modifier_map, ModifierKey key) {
474 for (size_t i = 0; i < modifier_map.size(); ++i) {
475 if (modifier_map[i].replacement == key) {
476 return true;
477 }
478 }
479 return false;
480 }
481
482 bool XKeyboard::SetCurrentKeyboardLayoutByName(const std::string& layout_name) {
483 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) { 480 if (SetLayoutInternal(layout_name, current_modifier_map_, false)) {
484 current_layout_name_ = layout_name; 481 current_layout_name_ = layout_name;
485 return true; 482 return true;
486 } 483 }
487 return false; 484 return false;
488 } 485 }
489 486
490 bool XKeyboard::ReapplyCurrentKeyboardLayout() { 487 bool XKeyboardImpl::ReapplyCurrentKeyboardLayout() {
491 if (current_layout_name_.empty()) { 488 if (current_layout_name_.empty()) {
492 LOG(ERROR) << "Can't reapply XKB layout: layout unknown"; 489 LOG(ERROR) << "Can't reapply XKB layout: layout unknown";
493 return false; 490 return false;
494 } 491 }
495 return SetLayoutInternal( 492 return SetLayoutInternal(
496 current_layout_name_, current_modifier_map_, true /* force */); 493 current_layout_name_, current_modifier_map_, true /* force */);
497 } 494 }
498 495
499 void XKeyboard::ReapplyCurrentModifierLockStatus() { 496 void XKeyboardImpl::ReapplyCurrentModifierLockStatus() {
500 SetLockedModifiers(current_caps_lock_status_ ? kEnableLock : kDisableLock, 497 SetLockedModifiers(current_caps_lock_status_ ? kEnableLock : kDisableLock,
501 current_num_lock_status_ ? kEnableLock : kDisableLock); 498 current_num_lock_status_ ? kEnableLock : kDisableLock);
502 } 499 }
503 500
504 bool XKeyboard::RemapModifierKeys(const ModifierMap& modifier_map) { 501 bool XKeyboardImpl::RemapModifierKeys(const ModifierMap& modifier_map) {
505 const std::string layout_name = current_layout_name_.empty() ? 502 const std::string layout_name = current_layout_name_.empty() ?
506 kDefaultLayoutName : current_layout_name_; 503 kDefaultLayoutName : current_layout_name_;
507 if (SetLayoutInternal(layout_name, modifier_map, false)) { 504 if (SetLayoutInternal(layout_name, modifier_map, false)) {
508 current_layout_name_ = layout_name; 505 current_layout_name_ = layout_name;
509 current_modifier_map_ = modifier_map; 506 current_modifier_map_ = modifier_map;
510 return true; 507 return true;
511 } 508 }
512 return false; 509 return false;
513 } 510 }
514 511
515 bool XKeyboard::KeepRightAlt(const std::string& xkb_layout_name) const { 512 bool XKeyboardImpl::KeepRightAlt(const std::string& xkb_layout_name) const {
516 return keep_right_alt_xkb_layout_names_.count(xkb_layout_name) > 0; 513 return keep_right_alt_xkb_layout_names_.count(xkb_layout_name) > 0;
517 } 514 }
518 515
519 bool XKeyboard::KeepCapsLock(const std::string& xkb_layout_name) const { 516 bool XKeyboardImpl::KeepCapsLock(const std::string& xkb_layout_name) const {
520 return caps_lock_remapped_xkb_layout_names_.count(xkb_layout_name) > 0; 517 return caps_lock_remapped_xkb_layout_names_.count(xkb_layout_name) > 0;
521 } 518 }
522 519
523 // static 520 // static
524 std::string XKeyboard::ModifierKeyToString(ModifierKey key) { 521 std::string XKeyboardImpl::ModifierKeyToString(ModifierKey key) {
525 switch (key) { 522 switch (key) {
526 case kSearchKey: 523 case kSearchKey:
527 return "search"; 524 return "search";
528 case kLeftControlKey: 525 case kLeftControlKey:
529 return "leftcontrol"; 526 return "leftcontrol";
530 case kLeftAltKey: 527 case kLeftAltKey:
531 return "leftalt"; 528 return "leftalt";
532 case kVoidKey: 529 case kVoidKey:
533 return "disabled"; 530 return "disabled";
534 case kCapsLockKey: 531 case kCapsLockKey:
535 return "capslock"; 532 return "capslock";
536 case kNumModifierKeys: 533 case kNumModifierKeys:
537 break; 534 break;
538 } 535 }
539 return ""; 536 return "";
540 } 537 }
541 538
539 // static
540 void XKeyboardImpl::OnSetLayoutFinish(pid_t pid,
541 int status,
542 XKeyboardImpl* self) {
543 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
544 VLOG(1) << "OnSetLayoutFinish: pid=" << pid;
545 if (self->execute_queue_.empty()) {
546 LOG(ERROR) << "OnSetLayoutFinish: execute_queue_ is empty. "
547 << "base::LaunchProcess failed? pid=" << pid;
548 return;
549 }
550 self->execute_queue_.pop();
551 self->MaybeExecuteSetLayoutCommand();
552 }
553
554 } // namespace
555
556 // static
557 bool XKeyboard::SetAutoRepeatEnabled(bool enabled) {
558 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
559 if (enabled) {
560 XAutoRepeatOn(ui::GetXDisplay());
561 } else {
562 XAutoRepeatOff(ui::GetXDisplay());
563 }
564 DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
565 return true;
566 }
567
568 // static
569 bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) {
570 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
571 DLOG(INFO) << "Set auto-repeat rate to: "
572 << rate.initial_delay_in_ms << " ms delay, "
573 << rate.repeat_interval_in_ms << " ms interval";
574 if (XkbSetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
575 rate.initial_delay_in_ms,
576 rate.repeat_interval_in_ms) != True) {
577 LOG(ERROR) << "Failed to set auto-repeat rate";
578 return false;
579 }
580 return true;
581 }
582
583 // static
584 bool XKeyboard::GetAutoRepeatEnabledForTesting() {
585 XKeyboardState state = {};
586 XGetKeyboardControl(ui::GetXDisplay(), &state);
587 return state.global_auto_repeat != AutoRepeatModeOff;
588 }
589
590 // static
591 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) {
592 return XkbGetAutoRepeatRate(ui::GetXDisplay(), XkbUseCoreKbd,
593 &(out_rate->initial_delay_in_ms),
594 &(out_rate->repeat_interval_in_ms)) == True;
595 }
596
597 // static
598 bool XKeyboard::ContainsModifierKeyAsReplacement(
599 const ModifierMap& modifier_map,
600 ModifierKey key) {
601 for (size_t i = 0; i < modifier_map.size(); ++i) {
602 if (modifier_map[i].replacement == key) {
603 return true;
604 }
605 }
606 return false;
607 }
608
609 // static
610 XKeyboard* XKeyboard::Create(const InputMethodUtil& util) {
611 return new XKeyboardImpl(util);
612 }
613
542 } // namespace input_method 614 } // namespace input_method
543 } // namespace chromeos 615 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/input_method/xkeyboard.h ('k') | chrome/browser/chromeos/input_method/xkeyboard_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698