OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chromeos/ime/xkeyboard.h" | 5 #include "chromeos/ime/keyboard_controller.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/bind.h" | 13 #include "base/bind.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" |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 | 105 |
106 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) != | 106 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) != |
107 std::string::npos) { | 107 std::string::npos) { |
108 DVLOG(1) << "Invalid layout_name: " << layout_name; | 108 DVLOG(1) << "Invalid layout_name: " << layout_name; |
109 return false; | 109 return false; |
110 } | 110 } |
111 | 111 |
112 return true; | 112 return true; |
113 } | 113 } |
114 | 114 |
115 class XKeyboardImpl : public XKeyboard { | 115 class KeyboardControllerX11 : public KeyboardController { |
116 public: | 116 public: |
117 XKeyboardImpl(); | 117 KeyboardControllerX11(); |
118 virtual ~XKeyboardImpl() {} | 118 virtual ~KeyboardControllerX11() {} |
119 | 119 |
120 // Overridden from XKeyboard: | 120 // Overridden from KeyboardController: |
121 virtual bool SetCurrentKeyboardLayoutByName( | 121 virtual bool SetCurrentKeyboardLayoutByName( |
122 const std::string& layout_name) OVERRIDE; | 122 const std::string& layout_name) OVERRIDE; |
123 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE; | 123 virtual bool ReapplyCurrentKeyboardLayout() OVERRIDE; |
124 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE; | 124 virtual void ReapplyCurrentModifierLockStatus() OVERRIDE; |
125 virtual void DisableNumLock() OVERRIDE; | 125 virtual void DisableNumLock() OVERRIDE; |
126 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE; | 126 virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE; |
127 virtual bool CapsLockIsEnabled() OVERRIDE; | 127 virtual bool CapsLockIsEnabled() OVERRIDE; |
128 virtual bool IsISOLevel5ShiftAvailable() const OVERRIDE; | 128 virtual bool IsISOLevel5ShiftAvailable() const OVERRIDE; |
129 virtual bool IsAltGrAvailable() const OVERRIDE; | 129 virtual bool IsAltGrAvailable() const OVERRIDE; |
130 virtual bool SetAutoRepeatEnabled(bool enabled) OVERRIDE; | 130 virtual bool SetAutoRepeatEnabled(bool enabled) OVERRIDE; |
(...skipping 29 matching lines...) Expand all Loading... |
160 bool current_caps_lock_status_; | 160 bool current_caps_lock_status_; |
161 | 161 |
162 // The XKB layout name which we set last time like "us" and "us(dvorak)". | 162 // The XKB layout name which we set last time like "us" and "us(dvorak)". |
163 std::string current_layout_name_; | 163 std::string current_layout_name_; |
164 | 164 |
165 // A queue for executing setxkbmap one by one. | 165 // A queue for executing setxkbmap one by one. |
166 std::queue<std::string> execute_queue_; | 166 std::queue<std::string> execute_queue_; |
167 | 167 |
168 base::ThreadChecker thread_checker_; | 168 base::ThreadChecker thread_checker_; |
169 | 169 |
170 base::WeakPtrFactory<XKeyboardImpl> weak_factory_; | 170 base::WeakPtrFactory<KeyboardControllerX11> weak_factory_; |
171 | 171 |
172 DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl); | 172 DISALLOW_COPY_AND_ASSIGN(KeyboardControllerX11); |
173 }; | 173 }; |
174 | 174 |
175 XKeyboardImpl::XKeyboardImpl() | 175 KeyboardControllerX11::KeyboardControllerX11() |
176 : is_running_on_chrome_os_(base::SysInfo::IsRunningOnChromeOS()), | 176 : is_running_on_chrome_os_(base::SysInfo::IsRunningOnChromeOS()), |
177 weak_factory_(this) { | 177 weak_factory_(this) { |
178 // X must be already initialized. | 178 // X must be already initialized. |
179 CHECK(GetXDisplay()); | 179 CHECK(GetXDisplay()); |
180 | 180 |
181 num_lock_mask_ = GetNumLockMask(); | 181 num_lock_mask_ = GetNumLockMask(); |
182 | 182 |
183 if (is_running_on_chrome_os_) { | 183 if (is_running_on_chrome_os_) { |
184 // Some code seems to assume that Mod2Mask is always assigned to | 184 // Some code seems to assume that Mod2Mask is always assigned to |
185 // Num Lock. | 185 // Num Lock. |
186 // | 186 // |
187 // TODO(yusukes): Check the assumption is really okay. If not, | 187 // TODO(yusukes): Check the assumption is really okay. If not, |
188 // modify the Aura code, and then remove the CHECK below. | 188 // modify the Aura code, and then remove the CHECK below. |
189 LOG_IF(ERROR, num_lock_mask_ != Mod2Mask) | 189 LOG_IF(ERROR, num_lock_mask_ != Mod2Mask) |
190 << "NumLock is not assigned to Mod2Mask. : " << num_lock_mask_; | 190 << "NumLock is not assigned to Mod2Mask. : " << num_lock_mask_; |
191 } | 191 } |
192 | 192 |
193 current_caps_lock_status_ = CapsLockIsEnabled(); | 193 current_caps_lock_status_ = CapsLockIsEnabled(); |
194 } | 194 } |
195 | 195 |
196 unsigned int XKeyboardImpl::GetNumLockMask() { | 196 unsigned int KeyboardControllerX11::GetNumLockMask() { |
197 DCHECK(thread_checker_.CalledOnValidThread()); | 197 DCHECK(thread_checker_.CalledOnValidThread()); |
198 static const unsigned int kBadMask = 0; | 198 static const unsigned int kBadMask = 0; |
199 | 199 |
200 unsigned int real_mask = kBadMask; | 200 unsigned int real_mask = kBadMask; |
201 XkbDescPtr xkb_desc = | 201 XkbDescPtr xkb_desc = |
202 XkbGetKeyboard(GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd); | 202 XkbGetKeyboard(GetXDisplay(), XkbAllComponentsMask, XkbUseCoreKbd); |
203 if (!xkb_desc) | 203 if (!xkb_desc) |
204 return kBadMask; | 204 return kBadMask; |
205 | 205 |
206 if (xkb_desc->dpy && xkb_desc->names) { | 206 if (xkb_desc->dpy && xkb_desc->names) { |
(...skipping 13 matching lines...) Expand all Loading... |
220 real_mask = kBadMask; // reset the return value, just in case. | 220 real_mask = kBadMask; // reset the return value, just in case. |
221 } | 221 } |
222 break; | 222 break; |
223 } | 223 } |
224 } | 224 } |
225 } | 225 } |
226 XkbFreeKeyboard(xkb_desc, 0, True /* free all components */); | 226 XkbFreeKeyboard(xkb_desc, 0, True /* free all components */); |
227 return real_mask; | 227 return real_mask; |
228 } | 228 } |
229 | 229 |
230 void XKeyboardImpl::SetLockedModifiers(bool caps_lock_enabled) { | 230 void KeyboardControllerX11::SetLockedModifiers(bool caps_lock_enabled) { |
231 DCHECK(thread_checker_.CalledOnValidThread()); | 231 DCHECK(thread_checker_.CalledOnValidThread()); |
232 | 232 |
233 // Always turn off num lock. | 233 // Always turn off num lock. |
234 unsigned int affect_mask = num_lock_mask_; | 234 unsigned int affect_mask = num_lock_mask_; |
235 unsigned int value_mask = 0; | 235 unsigned int value_mask = 0; |
236 | 236 |
237 affect_mask |= LockMask; | 237 affect_mask |= LockMask; |
238 value_mask |= (caps_lock_enabled ? LockMask : 0); | 238 value_mask |= (caps_lock_enabled ? LockMask : 0); |
239 current_caps_lock_status_ = caps_lock_enabled; | 239 current_caps_lock_status_ = caps_lock_enabled; |
240 | 240 |
241 XkbLockModifiers(GetXDisplay(), XkbUseCoreKbd, affect_mask, value_mask); | 241 XkbLockModifiers(GetXDisplay(), XkbUseCoreKbd, affect_mask, value_mask); |
242 } | 242 } |
243 | 243 |
244 bool XKeyboardImpl::SetLayoutInternal(const std::string& layout_name, | 244 bool KeyboardControllerX11::SetLayoutInternal(const std::string& layout_name, |
245 bool force) { | 245 bool force) { |
246 if (!is_running_on_chrome_os_) { | 246 if (!is_running_on_chrome_os_) { |
247 // We should not try to change a layout on Linux or inside ui_tests. Just | 247 // We should not try to change a layout on Linux or inside ui_tests. Just |
248 // return true. | 248 // return true. |
249 return true; | 249 return true; |
250 } | 250 } |
251 | 251 |
252 if (!CheckLayoutName(layout_name)) | 252 if (!CheckLayoutName(layout_name)) |
253 return false; | 253 return false; |
254 | 254 |
255 if (!force && (current_layout_name_ == layout_name)) { | 255 if (!force && (current_layout_name_ == layout_name)) { |
(...skipping 12 matching lines...) Expand all Loading... |
268 execute_queue_.push(layout_name); | 268 execute_queue_.push(layout_name); |
269 if (start_execution) | 269 if (start_execution) |
270 MaybeExecuteSetLayoutCommand(); | 270 MaybeExecuteSetLayoutCommand(); |
271 | 271 |
272 return true; | 272 return true; |
273 } | 273 } |
274 | 274 |
275 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name | 275 // Executes 'setxkbmap -layout ...' command asynchronously using a layout name |
276 // in the |execute_queue_|. Do nothing if the queue is empty. | 276 // in the |execute_queue_|. Do nothing if the queue is empty. |
277 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) | 277 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) |
278 void XKeyboardImpl::MaybeExecuteSetLayoutCommand() { | 278 void KeyboardControllerX11::MaybeExecuteSetLayoutCommand() { |
279 if (execute_queue_.empty()) | 279 if (execute_queue_.empty()) |
280 return; | 280 return; |
281 const std::string layout_to_set = execute_queue_.front(); | 281 const std::string layout_to_set = execute_queue_.front(); |
282 | 282 |
283 std::vector<std::string> argv; | 283 std::vector<std::string> argv; |
284 base::ProcessHandle handle = base::kNullProcessHandle; | 284 base::ProcessHandle handle = base::kNullProcessHandle; |
285 | 285 |
286 argv.push_back(kSetxkbmapCommand); | 286 argv.push_back(kSetxkbmapCommand); |
287 argv.push_back("-layout"); | 287 argv.push_back("-layout"); |
288 argv.push_back(layout_to_set); | 288 argv.push_back(layout_to_set); |
289 argv.push_back("-synch"); | 289 argv.push_back("-synch"); |
290 | 290 |
291 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) { | 291 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) { |
292 DVLOG(1) << "Failed to execute setxkbmap: " << layout_to_set; | 292 DVLOG(1) << "Failed to execute setxkbmap: " << layout_to_set; |
293 execute_queue_ = std::queue<std::string>(); // clear the queue. | 293 execute_queue_ = std::queue<std::string>(); // clear the queue. |
294 return; | 294 return; |
295 } | 295 } |
296 | 296 |
297 PollUntilChildFinish(handle); | 297 PollUntilChildFinish(handle); |
298 | 298 |
299 DVLOG(1) << "ExecuteSetLayoutCommand: " | 299 DVLOG(1) << "ExecuteSetLayoutCommand: " << layout_to_set |
300 << layout_to_set << ": pid=" << base::GetProcId(handle); | 300 << ": pid=" << base::GetProcId(handle); |
301 } | 301 } |
302 | 302 |
303 // Delay and loop until child process finishes and call the callback. | 303 // Delay and loop until child process finishes and call the callback. |
304 void XKeyboardImpl::PollUntilChildFinish(const base::ProcessHandle handle) { | 304 void KeyboardControllerX11::PollUntilChildFinish( |
| 305 const base::ProcessHandle handle) { |
305 int exit_code; | 306 int exit_code; |
306 DVLOG(1) << "PollUntilChildFinish: poll for pid=" << base::GetProcId(handle); | 307 DVLOG(1) << "PollUntilChildFinish: poll for pid=" << base::GetProcId(handle); |
307 switch (base::GetTerminationStatus(handle, &exit_code)) { | 308 switch (base::GetTerminationStatus(handle, &exit_code)) { |
308 case base::TERMINATION_STATUS_STILL_RUNNING: | 309 case base::TERMINATION_STATUS_STILL_RUNNING: |
309 DVLOG(1) << "PollUntilChildFinish: Try waiting again"; | 310 DVLOG(1) << "PollUntilChildFinish: Try waiting again"; |
310 base::MessageLoop::current()->PostDelayedTask( | 311 base::MessageLoop::current()->PostDelayedTask( |
311 FROM_HERE, | 312 FROM_HERE, |
312 base::Bind(&XKeyboardImpl::PollUntilChildFinish, | 313 base::Bind(&KeyboardControllerX11::PollUntilChildFinish, |
313 weak_factory_.GetWeakPtr(), handle), | 314 weak_factory_.GetWeakPtr(), |
| 315 handle), |
314 base::TimeDelta::FromMilliseconds(kSetLayoutCommandCheckDelayMs)); | 316 base::TimeDelta::FromMilliseconds(kSetLayoutCommandCheckDelayMs)); |
315 return; | 317 return; |
316 | 318 |
317 case base::TERMINATION_STATUS_NORMAL_TERMINATION: | 319 case base::TERMINATION_STATUS_NORMAL_TERMINATION: |
318 DVLOG(1) << "PollUntilChildFinish: Child process finished"; | 320 DVLOG(1) << "PollUntilChildFinish: Child process finished"; |
319 OnSetLayoutFinish(); | 321 OnSetLayoutFinish(); |
320 return; | 322 return; |
321 | 323 |
322 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: | 324 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: |
323 DVLOG(1) << "PollUntilChildFinish: Abnormal exit code: " << exit_code; | 325 DVLOG(1) << "PollUntilChildFinish: Abnormal exit code: " << exit_code; |
324 OnSetLayoutFinish(); | 326 OnSetLayoutFinish(); |
325 return; | 327 return; |
326 | 328 |
327 default: | 329 default: |
328 NOTIMPLEMENTED(); | 330 NOTIMPLEMENTED(); |
329 OnSetLayoutFinish(); | 331 OnSetLayoutFinish(); |
330 return; | 332 return; |
331 } | 333 } |
332 } | 334 } |
333 | 335 |
334 bool XKeyboardImpl::CapsLockIsEnabled() { | 336 bool KeyboardControllerX11::CapsLockIsEnabled() { |
335 DCHECK(thread_checker_.CalledOnValidThread()); | 337 DCHECK(thread_checker_.CalledOnValidThread()); |
336 XkbStateRec status; | 338 XkbStateRec status; |
337 XkbGetState(GetXDisplay(), XkbUseCoreKbd, &status); | 339 XkbGetState(GetXDisplay(), XkbUseCoreKbd, &status); |
338 return (status.locked_mods & LockMask); | 340 return (status.locked_mods & LockMask); |
339 } | 341 } |
340 | 342 |
341 bool XKeyboardImpl::IsISOLevel5ShiftAvailable() const { | 343 bool KeyboardControllerX11::IsISOLevel5ShiftAvailable() const { |
342 for (size_t i = 0; i < arraysize(kISOLevel5ShiftLayoutIds); ++i) { | 344 for (size_t i = 0; i < arraysize(kISOLevel5ShiftLayoutIds); ++i) { |
343 if (current_layout_name_ == kISOLevel5ShiftLayoutIds[i]) | 345 if (current_layout_name_ == kISOLevel5ShiftLayoutIds[i]) |
344 return true; | 346 return true; |
345 } | 347 } |
346 return false; | 348 return false; |
347 } | 349 } |
348 | 350 |
349 bool XKeyboardImpl::IsAltGrAvailable() const { | 351 bool KeyboardControllerX11::IsAltGrAvailable() const { |
350 for (size_t i = 0; i < arraysize(kAltGrLayoutIds); ++i) { | 352 for (size_t i = 0; i < arraysize(kAltGrLayoutIds); ++i) { |
351 if (current_layout_name_ == kAltGrLayoutIds[i]) | 353 if (current_layout_name_ == kAltGrLayoutIds[i]) |
352 return true; | 354 return true; |
353 } | 355 } |
354 return false; | 356 return false; |
355 } | 357 } |
356 | 358 |
357 | 359 bool KeyboardControllerX11::SetAutoRepeatEnabled(bool enabled) { |
358 bool XKeyboardImpl::SetAutoRepeatEnabled(bool enabled) { | |
359 if (enabled) | 360 if (enabled) |
360 XAutoRepeatOn(GetXDisplay()); | 361 XAutoRepeatOn(GetXDisplay()); |
361 else | 362 else |
362 XAutoRepeatOff(GetXDisplay()); | 363 XAutoRepeatOff(GetXDisplay()); |
363 DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); | 364 DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); |
364 return true; | 365 return true; |
365 } | 366 } |
366 | 367 |
367 bool XKeyboardImpl::SetAutoRepeatRate(const AutoRepeatRate& rate) { | 368 bool KeyboardControllerX11::SetAutoRepeatRate(const AutoRepeatRate& rate) { |
368 DVLOG(1) << "Set auto-repeat rate to: " | 369 DVLOG(1) << "Set auto-repeat rate to: " |
369 << rate.initial_delay_in_ms << " ms delay, " | 370 << rate.initial_delay_in_ms << " ms delay, " |
370 << rate.repeat_interval_in_ms << " ms interval"; | 371 << rate.repeat_interval_in_ms << " ms interval"; |
371 if (XkbSetAutoRepeatRate(GetXDisplay(), XkbUseCoreKbd, | 372 if (XkbSetAutoRepeatRate(GetXDisplay(), XkbUseCoreKbd, |
372 rate.initial_delay_in_ms, | 373 rate.initial_delay_in_ms, |
373 rate.repeat_interval_in_ms) != True) { | 374 rate.repeat_interval_in_ms) != True) { |
374 DVLOG(1) << "Failed to set auto-repeat rate"; | 375 DVLOG(1) << "Failed to set auto-repeat rate"; |
375 return false; | 376 return false; |
376 } | 377 } |
377 return true; | 378 return true; |
378 } | 379 } |
379 | 380 |
380 void XKeyboardImpl::SetCapsLockEnabled(bool enable_caps_lock) { | 381 void KeyboardControllerX11::SetCapsLockEnabled(bool enable_caps_lock) { |
381 SetLockedModifiers(enable_caps_lock); | 382 SetLockedModifiers(enable_caps_lock); |
382 } | 383 } |
383 | 384 |
384 bool XKeyboardImpl::SetCurrentKeyboardLayoutByName( | 385 bool KeyboardControllerX11::SetCurrentKeyboardLayoutByName( |
385 const std::string& layout_name) { | 386 const std::string& layout_name) { |
386 if (SetLayoutInternal(layout_name, false)) { | 387 if (SetLayoutInternal(layout_name, false)) { |
387 current_layout_name_ = layout_name; | 388 current_layout_name_ = layout_name; |
388 return true; | 389 return true; |
389 } | 390 } |
390 return false; | 391 return false; |
391 } | 392 } |
392 | 393 |
393 bool XKeyboardImpl::ReapplyCurrentKeyboardLayout() { | 394 bool KeyboardControllerX11::ReapplyCurrentKeyboardLayout() { |
394 if (current_layout_name_.empty()) { | 395 if (current_layout_name_.empty()) { |
395 DVLOG(1) << "Can't reapply XKB layout: layout unknown"; | 396 DVLOG(1) << "Can't reapply XKB layout: layout unknown"; |
396 return false; | 397 return false; |
397 } | 398 } |
398 return SetLayoutInternal(current_layout_name_, true /* force */); | 399 return SetLayoutInternal(current_layout_name_, true /* force */); |
399 } | 400 } |
400 | 401 |
401 void XKeyboardImpl::ReapplyCurrentModifierLockStatus() { | 402 void KeyboardControllerX11::ReapplyCurrentModifierLockStatus() { |
402 SetLockedModifiers(current_caps_lock_status_); | 403 SetLockedModifiers(current_caps_lock_status_); |
403 } | 404 } |
404 | 405 |
405 void XKeyboardImpl::DisableNumLock() { | 406 void KeyboardControllerX11::DisableNumLock() { |
406 SetCapsLockEnabled(current_caps_lock_status_); | 407 SetCapsLockEnabled(current_caps_lock_status_); |
407 } | 408 } |
408 | 409 |
409 void XKeyboardImpl::OnSetLayoutFinish() { | 410 void KeyboardControllerX11::OnSetLayoutFinish() { |
410 if (execute_queue_.empty()) { | 411 if (execute_queue_.empty()) { |
411 DVLOG(1) << "OnSetLayoutFinish: execute_queue_ is empty. " | 412 DVLOG(1) << "OnSetLayoutFinish: execute_queue_ is empty. " |
412 << "base::LaunchProcess failed?"; | 413 << "base::LaunchProcess failed?"; |
413 return; | 414 return; |
414 } | 415 } |
415 execute_queue_.pop(); | 416 execute_queue_.pop(); |
416 MaybeExecuteSetLayoutCommand(); | 417 MaybeExecuteSetLayoutCommand(); |
417 } | 418 } |
418 | 419 |
419 } // namespace | 420 } // namespace |
420 | 421 |
421 // static | 422 // static |
422 bool XKeyboard::GetAutoRepeatEnabledForTesting() { | 423 bool KeyboardController::GetAutoRepeatEnabledForTesting() { |
423 XKeyboardState state = {}; | 424 XKeyboardState state = {}; |
424 XGetKeyboardControl(GetXDisplay(), &state); | 425 XGetKeyboardControl(GetXDisplay(), &state); |
425 return state.global_auto_repeat != AutoRepeatModeOff; | 426 return state.global_auto_repeat != AutoRepeatModeOff; |
426 } | 427 } |
427 | 428 |
428 // static | 429 // static |
429 bool XKeyboard::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) { | 430 bool KeyboardController::GetAutoRepeatRateForTesting(AutoRepeatRate* out_rate) { |
430 return XkbGetAutoRepeatRate(GetXDisplay(), XkbUseCoreKbd, | 431 return XkbGetAutoRepeatRate(GetXDisplay(), |
| 432 XkbUseCoreKbd, |
431 &(out_rate->initial_delay_in_ms), | 433 &(out_rate->initial_delay_in_ms), |
432 &(out_rate->repeat_interval_in_ms)) == True; | 434 &(out_rate->repeat_interval_in_ms)) == True; |
433 } | 435 } |
434 | 436 |
435 // static | 437 // static |
436 bool XKeyboard::CheckLayoutNameForTesting(const std::string& layout_name) { | 438 bool KeyboardController::CheckLayoutNameForTesting( |
| 439 const std::string& layout_name) { |
437 return CheckLayoutName(layout_name); | 440 return CheckLayoutName(layout_name); |
438 } | 441 } |
439 | 442 |
440 // static | 443 // static |
441 XKeyboard* XKeyboard::Create() { | 444 KeyboardController* KeyboardController::Create() { |
442 return new XKeyboardImpl(); | 445 return new KeyboardControllerX11(); |
443 } | 446 } |
444 | 447 |
445 } // namespace input_method | 448 } // namespace input_method |
446 } // namespace chromeos | 449 } // namespace chromeos |
OLD | NEW |