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

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

Powered by Google App Engine
This is Rietveld 408576698