diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-28 07:50:55 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-28 07:50:55 +0000 |
commit | d24a7f958ad3f98673006f27fcd3c8c63ef29cbf (patch) | |
tree | f4c885b837090af38e206f1d56af43cc353703bf /remoting/host | |
parent | f02f6f5e35504369f8537b783766b9591dce4c35 (diff) | |
download | chromium_src-d24a7f958ad3f98673006f27fcd3c8c63ef29cbf.zip chromium_src-d24a7f958ad3f98673006f27fcd3c8c63ef29cbf.tar.gz chromium_src-d24a7f958ad3f98673006f27fcd3c8c63ef29cbf.tar.bz2 |
Update input injectors on Mac and Windows to handle TextEvent.
BUG=270356,265945
R=lambroslambrou@chromium.org
Review URL: https://codereview.chromium.org/214193002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host')
-rw-r--r-- | remoting/host/input_injector_mac.cc | 42 | ||||
-rw-r--r-- | remoting/host/input_injector_win.cc | 64 |
2 files changed, 68 insertions, 38 deletions
diff --git a/remoting/host/input_injector_mac.cc b/remoting/host/input_injector_mac.cc index b450674..30ea580 100644 --- a/remoting/host/input_injector_mac.cc +++ b/remoting/host/input_injector_mac.cc @@ -15,6 +15,7 @@ #include "base/mac/scoped_cftyperef.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" +#include "base/strings/utf_string_conversions.h" #include "remoting/host/clipboard.h" #include "remoting/proto/internal.pb.h" #include "remoting/protocol/message_decoder.h" @@ -30,6 +31,20 @@ void SetOrClearBit(uint64_t &value, uint64_t bit, bool set_bit) { value = set_bit ? (value | bit) : (value & ~bit); } +void CreateAndPostKeyEvent(int keycode, + bool pressed, + int flags, + const base::string16& unicode) { + base::ScopedCFTypeRef<CGEventRef> eventRef( + CGEventCreateKeyboardEvent(NULL, keycode, pressed)); + if (eventRef) { + CGEventSetFlags(eventRef, flags); + if (!unicode.empty()) + CGEventKeyboardSetUnicodeString(eventRef, unicode.size(), &(unicode[0])); + CGEventPost(kCGSessionEventTap, eventRef); + } +} + // This value is not defined. Give it the obvious name so that if it is ever // added there will be a handy compilation error to remind us to remove this // definition. @@ -194,24 +209,23 @@ void InputInjectorMac::Core::InjectKeyEvent(const KeyEvent& event) { SetOrClearBit(right_modifiers_, kCGEventFlagMaskAlternate, event.pressed()); } - base::ScopedCFTypeRef<CGEventRef> eventRef( - CGEventCreateKeyboardEvent(NULL, keycode, event.pressed())); - - if (eventRef) { - // In addition to the modifier keys pressed right now, we also need to set - // AlphaShift if caps lock was active at the client (Mac ignores NumLock). - uint64_t flags = left_modifiers_ | right_modifiers_; - if (event.lock_states() & protocol::KeyEvent::LOCK_STATES_CAPSLOCK) - flags |= kCGEventFlagMaskAlphaShift; - CGEventSetFlags(eventRef, flags); + // In addition to the modifier keys pressed right now, we also need to set + // AlphaShift if caps lock was active at the client (Mac ignores NumLock). + uint64_t flags = left_modifiers_ | right_modifiers_; + if (event.lock_states() & protocol::KeyEvent::LOCK_STATES_CAPSLOCK) + flags |= kCGEventFlagMaskAlphaShift; - // Post the event to the current session. - CGEventPost(kCGSessionEventTap, eventRef); - } + CreateAndPostKeyEvent(keycode, event.pressed(), flags, base::string16()); } void InputInjectorMac::Core::InjectTextEvent(const TextEvent& event) { - NOTIMPLEMENTED(); + DCHECK(event.has_text()); + base::string16 text = base::UTF8ToUTF16(event.text()); + + // Applications that ignore UnicodeString field will see the text event as + // Space key. + CreateAndPostKeyEvent(kVK_Space, true, 0, text); + CreateAndPostKeyEvent(kVK_Space, false, 0, text); } void InputInjectorMac::Core::InjectMouseEvent(const MouseEvent& event) { diff --git a/remoting/host/input_injector_win.cc b/remoting/host/input_injector_win.cc index 03e4b7e..235f45e 100644 --- a/remoting/host/input_injector_win.cc +++ b/remoting/host/input_injector_win.cc @@ -11,6 +11,8 @@ #include "base/location.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" #include "remoting/base/util.h" #include "remoting/host/clipboard.h" #include "remoting/proto/event.pb.h" @@ -20,6 +22,31 @@ namespace remoting { namespace { +// Helper used to call SendInput() API. +void SendKeyboardInput(uint32_t flags, uint16_t scancode) { + // Populate a Windows INPUT structure for the event. + INPUT input; + memset(&input, 0, sizeof(input)); + input.type = INPUT_KEYBOARD; + input.ki.time = 0; + input.ki.dwFlags = flags; + input.ki.wScan = scancode; + + if ((flags & KEYEVENTF_UNICODE) == 0) { + // Windows scancodes are only 8-bit, so store the low-order byte into the + // event and set the extended flag if any high-order bits are set. The only + // high-order values we should see are 0xE0 or 0xE1. The extended bit + // usually distinguishes keys with the same meaning, e.g. left & right + // shift. + input.ki.wScan &= 0xFF; + if ((scancode & 0xFF00) != 0x0000) + input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; + } + + if (SendInput(1, &input, sizeof(INPUT)) == 0) + LOG_GETLASTERROR(ERROR) << "Failed to inject a key event"; +} + using protocol::ClipboardEvent; using protocol::KeyEvent; using protocol::TextEvent; @@ -185,13 +212,11 @@ void InputInjectorWin::Core::Stop() { clipboard_->Stop(); } -InputInjectorWin::Core::~Core() { -} +InputInjectorWin::Core::~Core() {} void InputInjectorWin::Core::HandleKey(const KeyEvent& event) { // HostEventDispatcher should filter events missing the pressed field. - if (!event.has_pressed() || !event.has_usb_keycode()) - return; + DCHECK(event.has_pressed() && event.has_usb_keycode()); // Reset the system idle suspend timeout. SetThreadExecutionState(ES_SYSTEM_REQUIRED); @@ -205,29 +230,20 @@ void InputInjectorWin::Core::HandleKey(const KeyEvent& event) { if (scancode == key_converter->InvalidNativeKeycode()) return; - // Populate the a Windows INPUT structure for the event. - INPUT input; - memset(&input, 0, sizeof(input)); - input.type = INPUT_KEYBOARD; - input.ki.time = 0; - input.ki.dwFlags = KEYEVENTF_SCANCODE; - if (!event.pressed()) - input.ki.dwFlags |= KEYEVENTF_KEYUP; - - // Windows scancodes are only 8-bit, so store the low-order byte into the - // event and set the extended flag if any high-order bits are set. The only - // high-order values we should see are 0xE0 or 0xE1. The extended bit usually - // distinguishes keys with the same meaning, e.g. left & right shift. - input.ki.wScan = scancode & 0xFF; - if ((scancode & 0xFF00) != 0x0000) - input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; - - if (SendInput(1, &input, sizeof(INPUT)) == 0) - LOG_GETLASTERROR(ERROR) << "Failed to inject a key event"; + uint32_t flags = KEYEVENTF_SCANCODE | (event.pressed() ? 0 : KEYEVENTF_KEYUP); + SendKeyboardInput(flags, scancode); } void InputInjectorWin::Core::HandleText(const TextEvent& event) { - NOTIMPLEMENTED(); + // HostEventDispatcher should filter events missing the pressed field. + DCHECK(event.has_text()); + + base::string16 text = base::UTF8ToUTF16(event.text()); + for (base::string16::const_iterator it = text.begin(); + it != text.end(); ++it) { + SendKeyboardInput(KEYEVENTF_UNICODE, *it); + SendKeyboardInput(KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, *it); + } } void InputInjectorWin::Core::HandleMouse(const MouseEvent& event) { |