| 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 "chrome/browser/chromeos/input_method/input_method_engine.h" | 5 #include "chrome/browser/chromeos/input_method/input_method_engine.h" |
| 6 | 6 |
| 7 #define XK_MISCELLANY | |
| 8 #include <X11/keysymdef.h> | |
| 9 #include <X11/X.h> | |
| 10 #include <X11/Xlib.h> | |
| 11 #include <X11/Xutil.h> | |
| 12 #undef FocusIn | 7 #undef FocusIn |
| 13 #undef FocusOut | 8 #undef FocusOut |
| 14 #undef RootWindow | 9 #undef RootWindow |
| 15 #include <map> | 10 #include <map> |
| 16 | 11 |
| 17 #include "ash/ime/input_method_menu_item.h" | 12 #include "ash/ime/input_method_menu_item.h" |
| 18 #include "ash/ime/input_method_menu_manager.h" | 13 #include "ash/ime/input_method_menu_manager.h" |
| 19 #include "ash/shell.h" | 14 #include "ash/shell.h" |
| 20 #include "base/logging.h" | 15 #include "base/logging.h" |
| 21 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 22 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 23 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 24 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 25 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 26 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 27 #include "chromeos/ime/component_extension_ime_manager.h" | 22 #include "chromeos/ime/component_extension_ime_manager.h" |
| 28 #include "chromeos/ime/composition_text.h" | 23 #include "chromeos/ime/composition_text.h" |
| 29 #include "chromeos/ime/extension_ime_util.h" | 24 #include "chromeos/ime/extension_ime_util.h" |
| 30 #include "chromeos/ime/input_method_manager.h" | 25 #include "chromeos/ime/input_method_manager.h" |
| 31 #include "ui/aura/window.h" | 26 #include "ui/aura/window.h" |
| 32 #include "ui/aura/window_tree_host.h" | 27 #include "ui/aura/window_tree_host.h" |
| 33 #include "ui/base/ime/candidate_window.h" | 28 #include "ui/base/ime/candidate_window.h" |
| 34 #include "ui/base/ime/chromeos/ime_keymap.h" | 29 #include "ui/base/ime/chromeos/ime_keymap.h" |
| 35 #include "ui/events/event.h" | 30 #include "ui/events/event.h" |
| 36 #include "ui/events/event_processor.h" | 31 #include "ui/events/event_processor.h" |
| 37 #include "ui/events/keycodes/dom4/keycode_converter.h" | |
| 38 #include "ui/events/keycodes/keyboard_code_conversion_x.h" | |
| 39 #include "ui/keyboard/keyboard_controller.h" | 32 #include "ui/keyboard/keyboard_controller.h" |
| 40 #include "ui/keyboard/keyboard_util.h" | 33 #include "ui/keyboard/keyboard_util.h" |
| 41 | 34 |
| 42 namespace chromeos { | 35 namespace chromeos { |
| 43 const char* kErrorNotActive = "IME is not active"; | 36 const char* kErrorNotActive = "IME is not active"; |
| 44 const char* kErrorWrongContext = "Context is not active"; | 37 const char* kErrorWrongContext = "Context is not active"; |
| 45 const char* kCandidateNotFound = "Candidate not found"; | 38 const char* kCandidateNotFound = "Candidate not found"; |
| 46 | 39 |
| 47 namespace { | 40 namespace { |
| 48 | 41 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 63 size_t GetUtf8StringLength(const char* s) { | 56 size_t GetUtf8StringLength(const char* s) { |
| 64 size_t ret = 0; | 57 size_t ret = 0; |
| 65 while (*s) { | 58 while (*s) { |
| 66 if ((*s & 0xC0) != 0x80) | 59 if ((*s & 0xC0) != 0x80) |
| 67 ret++; | 60 ret++; |
| 68 ++s; | 61 ++s; |
| 69 } | 62 } |
| 70 return ret; | 63 return ret; |
| 71 } | 64 } |
| 72 | 65 |
| 66 std::string GetKeyFromEvent(const ui::KeyEvent& event) { |
| 67 const std::string& code = event.code(); |
| 68 if (StartsWithASCII(code, "Control", true)) |
| 69 return "Ctrl"; |
| 70 if (StartsWithASCII(code, "Shift", true)) |
| 71 return "Shift"; |
| 72 if (StartsWithASCII(code, "Alt", true)) |
| 73 return "Alt"; |
| 74 if (StartsWithASCII(code, "Arrow", true)) |
| 75 return code.substr(5); |
| 76 if (code == "Escape") |
| 77 return "Esc"; |
| 78 if (code == "Backspace" || code == "Tab" || |
| 79 code == "Enter" || code == "CapsLock") |
| 80 return code; |
| 81 uint16 ch = 0; |
| 82 // Ctrl+? cases, gets key value for Ctrl is not down. |
| 83 if (event.flags() & ui::EF_CONTROL_DOWN) { |
| 84 ui::KeyEvent event_no_ctrl(event.type(), |
| 85 event.key_code(), |
| 86 event.flags() ^ ui::EF_CONTROL_DOWN, |
| 87 false); |
| 88 ch = event_no_ctrl.GetCharacter(); |
| 89 } else { |
| 90 ch = event.GetCharacter(); |
| 91 } |
| 92 return base::UTF16ToUTF8(base::string16(1, ch)); |
| 93 } |
| 94 |
| 73 } // namespace | 95 } // namespace |
| 74 | 96 |
| 75 InputMethodEngine::InputMethodEngine() | 97 InputMethodEngine::InputMethodEngine() |
| 76 : current_input_type_(ui::TEXT_INPUT_TYPE_NONE), | 98 : current_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
| 77 active_(false), | 99 active_(false), |
| 78 context_id_(0), | 100 context_id_(0), |
| 79 next_context_id_(1), | 101 next_context_id_(1), |
| 80 composition_text_(new CompositionText()), | 102 composition_text_(new CompositionText()), |
| 81 composition_cursor_(0), | 103 composition_cursor_(0), |
| 82 candidate_window_(new ui::CandidateWindow()), | 104 candidate_window_(new ui::CandidateWindow()), |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 } | 281 } |
| 260 | 282 |
| 261 ui::EventProcessor* dispatcher = | 283 ui::EventProcessor* dispatcher = |
| 262 ash::Shell::GetPrimaryRootWindow()->GetHost()->event_processor(); | 284 ash::Shell::GetPrimaryRootWindow()->GetHost()->event_processor(); |
| 263 | 285 |
| 264 for (size_t i = 0; i < events.size(); ++i) { | 286 for (size_t i = 0; i < events.size(); ++i) { |
| 265 const KeyboardEvent& event = events[i]; | 287 const KeyboardEvent& event = events[i]; |
| 266 const ui::EventType type = | 288 const ui::EventType type = |
| 267 (event.type == "keyup") ? ui::ET_KEY_RELEASED : ui::ET_KEY_PRESSED; | 289 (event.type == "keyup") ? ui::ET_KEY_RELEASED : ui::ET_KEY_PRESSED; |
| 268 | 290 |
| 269 // KeyboardCodeFromXKyeSym assumes US keyboard layout. | |
| 270 ui::KeycodeConverter* conv = ui::KeycodeConverter::GetInstance(); | |
| 271 DCHECK(conv); | |
| 272 | |
| 273 // DOM code (KeyA) -> XKB -> XKeySym (XK_A) -> KeyboardCode (VKEY_A) | |
| 274 const uint16 native_keycode = | |
| 275 conv->CodeToNativeKeycode(event.code.c_str()); | |
| 276 const uint xkeysym = ui::DefaultXKeysymFromHardwareKeycode(native_keycode); | |
| 277 const ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(xkeysym); | |
| 278 | |
| 279 const std::string code = event.code; | |
| 280 int flags = ui::EF_NONE; | 291 int flags = ui::EF_NONE; |
| 281 flags |= event.alt_key ? ui::EF_ALT_DOWN : ui::EF_NONE; | 292 flags |= event.alt_key ? ui::EF_ALT_DOWN : ui::EF_NONE; |
| 282 flags |= event.ctrl_key ? ui::EF_CONTROL_DOWN : ui::EF_NONE; | 293 flags |= event.ctrl_key ? ui::EF_CONTROL_DOWN : ui::EF_NONE; |
| 283 flags |= event.shift_key ? ui::EF_SHIFT_DOWN : ui::EF_NONE; | 294 flags |= event.shift_key ? ui::EF_SHIFT_DOWN : ui::EF_NONE; |
| 284 flags |= event.caps_lock ? ui::EF_CAPS_LOCK_DOWN : ui::EF_NONE; | 295 flags |= event.caps_lock ? ui::EF_CAPS_LOCK_DOWN : ui::EF_NONE; |
| 285 | 296 |
| 286 ui::KeyEvent ui_event(type, key_code, code, flags, false /* is_char */); | 297 ui::KeyEvent ui_event(type, |
| 298 ui::DomCode2KeyboardCode(event.code), |
| 299 event.code, |
| 300 flags, |
| 301 false /* is_char */); |
| 302 if (!event.key.empty()) |
| 303 ui_event.set_character(base::UTF8ToUTF16(event.key)[0]); |
| 287 base::AutoReset<const ui::KeyEvent*> reset_sent_key(&sent_key_event_, | 304 base::AutoReset<const ui::KeyEvent*> reset_sent_key(&sent_key_event_, |
| 288 &ui_event); | 305 &ui_event); |
| 289 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&ui_event); | 306 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&ui_event); |
| 290 if (details.dispatcher_destroyed) | 307 if (details.dispatcher_destroyed) |
| 291 break; | 308 break; |
| 292 } | 309 } |
| 293 return true; | 310 return true; |
| 294 } | 311 } |
| 295 | 312 |
| 296 const InputMethodEngine::CandidateWindowProperty& | 313 const InputMethodEngine::CandidateWindowProperty& |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 | 594 |
| 578 void InputMethodEngine::PropertyActivate(const std::string& property_name) { | 595 void InputMethodEngine::PropertyActivate(const std::string& property_name) { |
| 579 observer_->OnMenuItemActivated(engine_id_, property_name); | 596 observer_->OnMenuItemActivated(engine_id_, property_name); |
| 580 } | 597 } |
| 581 | 598 |
| 582 void InputMethodEngine::Reset() { | 599 void InputMethodEngine::Reset() { |
| 583 observer_->OnReset(engine_id_); | 600 observer_->OnReset(engine_id_); |
| 584 } | 601 } |
| 585 | 602 |
| 586 namespace { | 603 namespace { |
| 604 |
| 587 void GetExtensionKeyboardEventFromKeyEvent( | 605 void GetExtensionKeyboardEventFromKeyEvent( |
| 588 const ui::KeyEvent& event, | 606 const ui::KeyEvent& event, |
| 589 InputMethodEngine::KeyboardEvent* ext_event) { | 607 InputMethodEngine::KeyboardEvent* ext_event) { |
| 590 DCHECK(event.type() == ui::ET_KEY_RELEASED || | 608 DCHECK(event.type() == ui::ET_KEY_RELEASED || |
| 591 event.type() == ui::ET_KEY_PRESSED); | 609 event.type() == ui::ET_KEY_PRESSED); |
| 592 DCHECK(ext_event); | 610 DCHECK(ext_event); |
| 593 ext_event->type = (event.type() == ui::ET_KEY_RELEASED) ? "keyup" : "keydown"; | 611 ext_event->type = (event.type() == ui::ET_KEY_RELEASED) ? "keyup" : "keydown"; |
| 594 | 612 |
| 595 ext_event->code = event.code(); | 613 ext_event->code = event.code(); |
| 596 ext_event->alt_key = event.IsAltDown(); | 614 ext_event->alt_key = event.IsAltDown(); |
| 597 ext_event->ctrl_key = event.IsControlDown(); | 615 ext_event->ctrl_key = event.IsControlDown(); |
| 598 ext_event->shift_key = event.IsShiftDown(); | 616 ext_event->shift_key = event.IsShiftDown(); |
| 599 ext_event->caps_lock = event.IsCapsLockDown(); | 617 ext_event->caps_lock = event.IsCapsLockDown(); |
| 618 ext_event->key = GetKeyFromEvent(event); |
| 619 } |
| 600 | 620 |
| 601 uint32 x11_keysym = 0; | |
| 602 if (event.HasNativeEvent()) { | |
| 603 const base::NativeEvent& native_event = event.native_event(); | |
| 604 DCHECK(native_event); | |
| 605 | |
| 606 XKeyEvent* x_key = &(static_cast<XEvent*>(native_event)->xkey); | |
| 607 KeySym keysym = NoSymbol; | |
| 608 ::XLookupString(x_key, NULL, 0, &keysym, NULL); | |
| 609 x11_keysym = keysym; | |
| 610 } else { | |
| 611 // Convert ui::KeyEvent.key_code to DOM UIEvent key. | |
| 612 // XKeysymForWindowsKeyCode converts key_code to XKeySym, but it | |
| 613 // assumes US layout and does not care about CapLock state. | |
| 614 // | |
| 615 // TODO(komatsu): Support CapsLock states. | |
| 616 // TODO(komatsu): Support non-us keyboard layouts. | |
| 617 x11_keysym = ui::XKeysymForWindowsKeyCode(event.key_code(), | |
| 618 event.IsShiftDown()); | |
| 619 } | |
| 620 ext_event->key = ui::FromXKeycodeToKeyValue(x11_keysym); | |
| 621 } | |
| 622 } // namespace | 621 } // namespace |
| 623 | 622 |
| 624 void InputMethodEngine::ProcessKeyEvent( | 623 void InputMethodEngine::ProcessKeyEvent( |
| 625 const ui::KeyEvent& key_event, | 624 const ui::KeyEvent& key_event, |
| 626 const KeyEventDoneCallback& callback) { | 625 const KeyEventDoneCallback& callback) { |
| 627 | 626 |
| 628 KeyEventDoneCallback *handler = new KeyEventDoneCallback(); | 627 KeyEventDoneCallback *handler = new KeyEventDoneCallback(); |
| 629 *handler = callback; | 628 *handler = callback; |
| 630 | 629 |
| 631 KeyboardEvent ext_event; | 630 KeyboardEvent ext_event; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 // TODO(nona): Implement it. | 698 // TODO(nona): Implement it. |
| 700 break; | 699 break; |
| 701 } | 700 } |
| 702 } | 701 } |
| 703 } | 702 } |
| 704 | 703 |
| 705 // TODO(nona): Support item.children. | 704 // TODO(nona): Support item.children. |
| 706 } | 705 } |
| 707 | 706 |
| 708 } // namespace chromeos | 707 } // namespace chromeos |
| OLD | NEW |