Commit d24a7f95 authored by sergeyu@chromium.org's avatar sergeyu@chromium.org

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
parent f02f6f5e
......@@ -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) {
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment