Commit f297c517 authored by Jamie Walch's avatar Jamie Walch Committed by Commit Bot

Add support for keyboard input for the terminate_on_input option.

Change-Id: I402f691a57d73ca287441d202034418f5a9a3920
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1726905
Commit-Queue: Jamie Walch <jamiewalch@chromium.org>
Reviewed-by: default avatarGary Kacmarcik <garykac@chromium.org>
Reviewed-by: default avatarDenis Kuznetsov <antrim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#688721}
parent 5bd8b22f
...@@ -454,6 +454,13 @@ void ClientSession::DisconnectSession(protocol::ErrorCode error) { ...@@ -454,6 +454,13 @@ void ClientSession::DisconnectSession(protocol::ErrorCode error) {
connection_->Disconnect(error); connection_->Disconnect(error);
} }
void ClientSession::OnLocalKeyPressed(uint32_t usb_keycode) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool is_local = remote_input_filter_.LocalKeyPressed(usb_keycode);
if (is_local && desktop_environment_options_.terminate_upon_input())
DisconnectSession(protocol::OK);
}
void ClientSession::OnLocalPointerMoved(const webrtc::DesktopVector& position, void ClientSession::OnLocalPointerMoved(const webrtc::DesktopVector& position,
ui::EventType type) { ui::EventType type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
......
...@@ -134,6 +134,7 @@ class ClientSession : public protocol::HostStub, ...@@ -134,6 +134,7 @@ class ClientSession : public protocol::HostStub,
// ClientSessionControl interface. // ClientSessionControl interface.
const std::string& client_jid() const override; const std::string& client_jid() const override;
void DisconnectSession(protocol::ErrorCode error) override; void DisconnectSession(protocol::ErrorCode error) override;
void OnLocalKeyPressed(uint32_t usb_keycode) override;
void OnLocalPointerMoved(const webrtc::DesktopVector& position, void OnLocalPointerMoved(const webrtc::DesktopVector& position,
ui::EventType type) override; ui::EventType type) override;
void SetDisableInputs(bool disable_inputs) override; void SetDisableInputs(bool disable_inputs) override;
......
...@@ -36,6 +36,9 @@ class ClientSessionControl { ...@@ -36,6 +36,9 @@ class ClientSessionControl {
virtual void OnLocalPointerMoved(const webrtc::DesktopVector& position, virtual void OnLocalPointerMoved(const webrtc::DesktopVector& position,
ui::EventType type) = 0; ui::EventType type) = 0;
// Called when a local key press or release is detected.
virtual void OnLocalKeyPressed(uint32_t usb_keycode) = 0;
// Disables or enables the remote input in the client session. // Disables or enables the remote input in the client session.
virtual void SetDisableInputs(bool disable_inputs) = 0; virtual void SetDisableInputs(bool disable_inputs) = 0;
......
...@@ -313,6 +313,12 @@ void DesktopSessionAgent::DisconnectSession(protocol::ErrorCode error) { ...@@ -313,6 +313,12 @@ void DesktopSessionAgent::DisconnectSession(protocol::ErrorCode error) {
std::make_unique<ChromotingDesktopNetworkMsg_DisconnectSession>(error)); std::make_unique<ChromotingDesktopNetworkMsg_DisconnectSession>(error));
} }
void DesktopSessionAgent::OnLocalKeyPressed(uint32_t usb_keycode) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
remote_input_filter_->LocalKeyPressed(usb_keycode);
}
void DesktopSessionAgent::OnLocalPointerMoved( void DesktopSessionAgent::OnLocalPointerMoved(
const webrtc::DesktopVector& new_pos, const webrtc::DesktopVector& new_pos,
ui::EventType type) { ui::EventType type) {
......
...@@ -127,6 +127,7 @@ class DesktopSessionAgent ...@@ -127,6 +127,7 @@ class DesktopSessionAgent
// ClientSessionControl interface. // ClientSessionControl interface.
const std::string& client_jid() const override; const std::string& client_jid() const override;
void DisconnectSession(protocol::ErrorCode error) override; void DisconnectSession(protocol::ErrorCode error) override;
void OnLocalKeyPressed(uint32_t usb_keycode) override;
void OnLocalPointerMoved(const webrtc::DesktopVector& position, void OnLocalPointerMoved(const webrtc::DesktopVector& position,
ui::EventType type) override; ui::EventType type) override;
void SetDisableInputs(bool disable_inputs) override; void SetDisableInputs(bool disable_inputs) override;
......
...@@ -108,7 +108,7 @@ class DisconnectWindowWin : public HostWindow { ...@@ -108,7 +108,7 @@ class DisconnectWindowWin : public HostWindow {
ui::EventType type); ui::EventType type);
// Called when local keyboard event is seen and shows the dialog (if hidden). // Called when local keyboard event is seen and shows the dialog (if hidden).
void OnLocalKeyboardEvent(); void OnLocalKeyPressed(uint32_t usb_keycode);
// Used to disconnect the client session. // Used to disconnect the client session.
base::WeakPtr<ClientSessionControl> client_session_control_; base::WeakPtr<ClientSessionControl> client_session_control_;
...@@ -195,7 +195,7 @@ void DisconnectWindowWin::Start( ...@@ -195,7 +195,7 @@ void DisconnectWindowWin::Start(
local_input_monitor_->StartMonitoring( local_input_monitor_->StartMonitoring(
base::BindRepeating(&DisconnectWindowWin::OnLocalMouseEvent, base::BindRepeating(&DisconnectWindowWin::OnLocalMouseEvent,
weak_factory_.GetWeakPtr()), weak_factory_.GetWeakPtr()),
base::BindRepeating(&DisconnectWindowWin::OnLocalKeyboardEvent, base::BindRepeating(&DisconnectWindowWin::OnLocalKeyPressed,
weak_factory_.GetWeakPtr()), weak_factory_.GetWeakPtr()),
base::BindRepeating(&DisconnectWindowWin::StopAutoHideBehavior, base::BindRepeating(&DisconnectWindowWin::StopAutoHideBehavior,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
...@@ -405,7 +405,7 @@ void DisconnectWindowWin::OnLocalMouseEvent( ...@@ -405,7 +405,7 @@ void DisconnectWindowWin::OnLocalMouseEvent(
mouse_position_ = position; mouse_position_ = position;
} }
void DisconnectWindowWin::OnLocalKeyboardEvent() { void DisconnectWindowWin::OnLocalKeyPressed(uint32_t usb_keycode) {
// Show the dialog before setting |local_input_seen_|. That way the dialog // Show the dialog before setting |local_input_seen_|. That way the dialog
// will be shown in the center position and subsequent reshows will honor // will be shown in the center position and subsequent reshows will honor
// the new position (if any) the dialog is moved to. // the new position (if any) the dialog is moved to.
......
...@@ -71,6 +71,7 @@ class MockClientSessionControl : public ClientSessionControl { ...@@ -71,6 +71,7 @@ class MockClientSessionControl : public ClientSessionControl {
MOCK_METHOD1(DisconnectSession, void(protocol::ErrorCode error)); MOCK_METHOD1(DisconnectSession, void(protocol::ErrorCode error));
MOCK_METHOD2(OnLocalPointerMoved, MOCK_METHOD2(OnLocalPointerMoved,
void(const webrtc::DesktopVector&, ui::EventType)); void(const webrtc::DesktopVector&, ui::EventType));
MOCK_METHOD1(OnLocalKeyPressed, void(uint32_t));
MOCK_METHOD1(SetDisableInputs, void(bool)); MOCK_METHOD1(SetDisableInputs, void(bool));
MOCK_METHOD0(ResetVideoPipeline, void()); MOCK_METHOD0(ResetVideoPipeline, void());
MOCK_METHOD1(OnDesktopDisplayChanged, MOCK_METHOD1(OnDesktopDisplayChanged,
......
...@@ -44,6 +44,7 @@ class HostWindowProxy::Core ...@@ -44,6 +44,7 @@ class HostWindowProxy::Core
// ClientSessionControl interface. // ClientSessionControl interface.
const std::string& client_jid() const override; const std::string& client_jid() const override;
void DisconnectSession(protocol::ErrorCode error) override; void DisconnectSession(protocol::ErrorCode error) override;
void OnLocalKeyPressed(uint32_t usb_keycode) override;
void OnLocalPointerMoved(const webrtc::DesktopVector& position, void OnLocalPointerMoved(const webrtc::DesktopVector& position,
ui::EventType type) override; ui::EventType type) override;
void SetDisableInputs(bool disable_inputs) override; void SetDisableInputs(bool disable_inputs) override;
...@@ -161,6 +162,17 @@ void HostWindowProxy::Core::DisconnectSession(protocol::ErrorCode error) { ...@@ -161,6 +162,17 @@ void HostWindowProxy::Core::DisconnectSession(protocol::ErrorCode error) {
client_session_control_->DisconnectSession(error); client_session_control_->DisconnectSession(error);
} }
void HostWindowProxy::Core::OnLocalKeyPressed(uint32_t usb_keycode) {
if (!caller_task_runner_->BelongsToCurrentThread()) {
caller_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&Core::OnLocalKeyPressed, this, usb_keycode));
return;
}
if (client_session_control_.get())
client_session_control_->OnLocalKeyPressed(usb_keycode);
}
void HostWindowProxy::Core::OnLocalPointerMoved( void HostWindowProxy::Core::OnLocalPointerMoved(
const webrtc::DesktopVector& position, const webrtc::DesktopVector& position,
ui::EventType type) { ui::EventType type) {
......
...@@ -30,7 +30,7 @@ class LocalInputMonitorImpl : public LocalInputMonitor { ...@@ -30,7 +30,7 @@ class LocalInputMonitorImpl : public LocalInputMonitor {
void StartMonitoringForClientSession( void StartMonitoringForClientSession(
base::WeakPtr<ClientSessionControl> client_session_control) override; base::WeakPtr<ClientSessionControl> client_session_control) override;
void StartMonitoring(PointerMoveCallback on_pointer_input, void StartMonitoring(PointerMoveCallback on_pointer_input,
base::RepeatingClosure on_keyboard_input, KeyPressedCallback on_keyboard_input,
base::RepeatingClosure on_error) override; base::RepeatingClosure on_error) override;
private: private:
...@@ -90,12 +90,19 @@ void LocalInputMonitorImpl::StartMonitoringForClientSession( ...@@ -90,12 +90,19 @@ void LocalInputMonitorImpl::StartMonitoringForClientSession(
base::BindOnce(&ClientSessionControl::DisconnectSession, base::BindOnce(&ClientSessionControl::DisconnectSession,
client_session_control, protocol::OK)); client_session_control, protocol::OK));
keyboard_input_monitor_ = LocalKeyboardInputMonitor::Create(
caller_task_runner_, input_task_runner_, ui_task_runner_,
base::BindRepeating(&ClientSessionControl::OnLocalKeyPressed,
client_session_control),
base::BindOnce(&ClientSessionControl::DisconnectSession,
client_session_control, protocol::OK));
OnMonitoringStarted(); OnMonitoringStarted();
} }
void LocalInputMonitorImpl::StartMonitoring( void LocalInputMonitorImpl::StartMonitoring(
PointerMoveCallback on_pointer_input, PointerMoveCallback on_pointer_input,
base::RepeatingClosure on_keyboard_input, KeyPressedCallback on_keyboard_input,
base::RepeatingClosure on_error) { base::RepeatingClosure on_error) {
DCHECK(!monitoring_); DCHECK(!monitoring_);
DCHECK(on_error); DCHECK(on_error);
......
...@@ -31,6 +31,7 @@ class LocalInputMonitor { ...@@ -31,6 +31,7 @@ class LocalInputMonitor {
using PointerMoveCallback = using PointerMoveCallback =
base::RepeatingCallback<void(const webrtc::DesktopVector&, base::RepeatingCallback<void(const webrtc::DesktopVector&,
ui::EventType)>; ui::EventType)>;
using KeyPressedCallback = base::RepeatingCallback<void(uint32_t)>;
virtual ~LocalInputMonitor() = default; virtual ~LocalInputMonitor() = default;
...@@ -43,7 +44,7 @@ class LocalInputMonitor { ...@@ -43,7 +44,7 @@ class LocalInputMonitor {
// Start monitoring and notify using |client_session_control|. In this mode // Start monitoring and notify using |client_session_control|. In this mode
// the LocalInputMonitor will listen for session disconnect hotkeys and mouse // the LocalInputMonitor will listen for session disconnect hotkeys and mouse
// events (and touch, on some platforms) for input filtering. // and keyboard events (and touch, on some platforms) for input filtering.
virtual void StartMonitoringForClientSession( virtual void StartMonitoringForClientSession(
base::WeakPtr<ClientSessionControl> client_session_control) = 0; base::WeakPtr<ClientSessionControl> client_session_control) = 0;
...@@ -54,7 +55,7 @@ class LocalInputMonitor { ...@@ -54,7 +55,7 @@ class LocalInputMonitor {
// |on_keyboard_input| is called for each keypress detected. // |on_keyboard_input| is called for each keypress detected.
// |on_error| is called if any of the child input monitors fail. // |on_error| is called if any of the child input monitors fail.
virtual void StartMonitoring(PointerMoveCallback on_pointer_input, virtual void StartMonitoring(PointerMoveCallback on_pointer_input,
base::RepeatingClosure on_keyboard_input, KeyPressedCallback on_keyboard_input,
base::RepeatingClosure on_error) = 0; base::RepeatingClosure on_error) = 0;
protected: protected:
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "remoting/host/input_monitor/local_input_monitor.h"
namespace base { namespace base {
class SingleThreadTaskRunner; class SingleThreadTaskRunner;
...@@ -30,7 +31,7 @@ class LocalKeyboardInputMonitor { ...@@ -30,7 +31,7 @@ class LocalKeyboardInputMonitor {
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::RepeatingClosure on_key_event_callback, LocalInputMonitor::KeyPressedCallback on_key_event_callback,
base::OnceClosure disconnect_callback); base::OnceClosure disconnect_callback);
protected: protected:
......
...@@ -6,18 +6,119 @@ ...@@ -6,18 +6,119 @@
#include <utility> #include <utility>
#include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "remoting/host/chromeos/point_transformer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/platform/platform_event_observer.h"
#include "ui/events/platform/platform_event_source.h"
namespace remoting { namespace remoting {
namespace {
class LocalKeyboardInputMonitorChromeos : public LocalKeyboardInputMonitor {
public:
LocalKeyboardInputMonitorChromeos(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
LocalInputMonitor::KeyPressedCallback key_pressed_callback);
~LocalKeyboardInputMonitorChromeos() override;
private:
class Core : ui::PlatformEventObserver {
public:
Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
LocalInputMonitor::KeyPressedCallback on_key_event_callback);
~Core() override;
void Start();
// ui::PlatformEventObserver interface.
void WillProcessEvent(const ui::PlatformEvent& event) override;
void DidProcessEvent(const ui::PlatformEvent& event) override;
private:
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
LocalInputMonitor::KeyPressedCallback key_pressed_callback_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
// Task runner on which ui::events are received.
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
std::unique_ptr<Core> core_;
DISALLOW_COPY_AND_ASSIGN(LocalKeyboardInputMonitorChromeos);
};
LocalKeyboardInputMonitorChromeos::LocalKeyboardInputMonitorChromeos(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
LocalInputMonitor::KeyPressedCallback key_pressed_callback)
: input_task_runner_(input_task_runner),
core_(new Core(caller_task_runner, std::move(key_pressed_callback))) {
input_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&Core::Start, base::Unretained(core_.get())));
}
LocalKeyboardInputMonitorChromeos::~LocalKeyboardInputMonitorChromeos() {
input_task_runner_->DeleteSoon(FROM_HERE, core_.release());
}
LocalKeyboardInputMonitorChromeos::Core::Core(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
LocalInputMonitor::KeyPressedCallback key_pressed_callback)
: caller_task_runner_(caller_task_runner),
key_pressed_callback_(std::move(key_pressed_callback)) {}
void LocalKeyboardInputMonitorChromeos::Core::Start() {
// TODO(erg): Need to handle the mus case where PlatformEventSource is null
// because we are in mus. This class looks like it can be rewritten with mus
// EventMatchers.
if (ui::PlatformEventSource::GetInstance()) {
ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
}
}
LocalKeyboardInputMonitorChromeos::Core::~Core() {
if (ui::PlatformEventSource::GetInstance()) {
ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
}
}
void LocalKeyboardInputMonitorChromeos::Core::WillProcessEvent(
const ui::PlatformEvent& event) {
// No need to handle this callback.
}
void LocalKeyboardInputMonitorChromeos::Core::DidProcessEvent(
const ui::PlatformEvent& event) {
ui::EventType type = ui::EventTypeFromNative(event);
if (type == ui::ET_KEY_PRESSED) {
ui::DomCode dom_code = ui::CodeFromNative(event);
uint32_t usb_keycode = ui::KeycodeConverter::DomCodeToUsbKeycode(dom_code);
caller_task_runner_->PostTask(
FROM_HERE, base::BindOnce(key_pressed_callback_, usb_keycode));
}
}
} // namespace
std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create( std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::RepeatingClosure on_key_event_callback, LocalInputMonitor::KeyPressedCallback on_key_event_callback,
base::OnceClosure disconnect_callback) { base::OnceClosure disconnect_callback) {
return nullptr; return std::make_unique<LocalKeyboardInputMonitorChromeos>(
caller_task_runner, input_task_runner, std::move(on_key_event_callback));
} }
} // namespace remoting } // namespace remoting
...@@ -15,7 +15,7 @@ std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create( ...@@ -15,7 +15,7 @@ std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::RepeatingClosure on_key_event_callback, LocalInputMonitor::KeyPressedCallback on_key_event_callback,
base::OnceClosure disconnect_callback) { base::OnceClosure disconnect_callback) {
return nullptr; return nullptr;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/location.h" #include "base/location.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "remoting/host/input_monitor/local_input_monitor_win.h" #include "remoting/host/input_monitor/local_input_monitor_win.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace remoting { namespace remoting {
...@@ -26,7 +27,7 @@ class KeyboardRawInputHandlerWin ...@@ -26,7 +27,7 @@ class KeyboardRawInputHandlerWin
KeyboardRawInputHandlerWin( KeyboardRawInputHandlerWin(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::RepeatingClosure on_key_event_callback, LocalInputMonitor::KeyPressedCallback on_key_event_callback,
base::OnceClosure disconnect_callback); base::OnceClosure disconnect_callback);
~KeyboardRawInputHandlerWin() override; ~KeyboardRawInputHandlerWin() override;
...@@ -39,7 +40,7 @@ class KeyboardRawInputHandlerWin ...@@ -39,7 +40,7 @@ class KeyboardRawInputHandlerWin
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
base::RepeatingClosure on_key_event_callback_; LocalInputMonitor::KeyPressedCallback on_key_event_callback_;
base::OnceClosure disconnect_callback_; base::OnceClosure disconnect_callback_;
// Tracks whether the instance is registered to receive raw input events. // Tracks whether the instance is registered to receive raw input events.
...@@ -51,7 +52,7 @@ class KeyboardRawInputHandlerWin ...@@ -51,7 +52,7 @@ class KeyboardRawInputHandlerWin
KeyboardRawInputHandlerWin::KeyboardRawInputHandlerWin( KeyboardRawInputHandlerWin::KeyboardRawInputHandlerWin(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::RepeatingClosure on_key_event_callback, LocalInputMonitor::KeyPressedCallback on_key_event_callback,
base::OnceClosure disconnect_callback) base::OnceClosure disconnect_callback)
: caller_task_runner_(caller_task_runner), : caller_task_runner_(caller_task_runner),
ui_task_runner_(ui_task_runner), ui_task_runner_(ui_task_runner),
...@@ -99,7 +100,12 @@ void KeyboardRawInputHandlerWin::OnInputEvent(const RAWINPUT* input) { ...@@ -99,7 +100,12 @@ void KeyboardRawInputHandlerWin::OnInputEvent(const RAWINPUT* input) {
if (input->header.dwType == RIM_TYPEKEYBOARD && if (input->header.dwType == RIM_TYPEKEYBOARD &&
input->header.hDevice != nullptr) { input->header.hDevice != nullptr) {
caller_task_runner_->PostTask(FROM_HERE, on_key_event_callback_); USHORT vkey = input->data.keyboard.VKey;
UINT scancode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
uint32_t usb_keycode =
ui::KeycodeConverter::NativeKeycodeToUsbKeycode(scancode);
caller_task_runner_->PostTask(
FROM_HERE, base::BindOnce(on_key_event_callback_, usb_keycode));
} }
} }
...@@ -133,7 +139,7 @@ std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create( ...@@ -133,7 +139,7 @@ std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::RepeatingClosure on_key_event_callback, LocalInputMonitor::KeyPressedCallback on_key_event_callback,
base::OnceClosure disconnect_callback) { base::OnceClosure disconnect_callback) {
auto raw_input_handler = std::make_unique<KeyboardRawInputHandlerWin>( auto raw_input_handler = std::make_unique<KeyboardRawInputHandlerWin>(
caller_task_runner, ui_task_runner, std::move(on_key_event_callback), caller_task_runner, ui_task_runner, std::move(on_key_event_callback),
......
...@@ -15,7 +15,7 @@ std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create( ...@@ -15,7 +15,7 @@ std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::RepeatingClosure on_key_event_callback, LocalInputMonitor::KeyPressedCallback on_key_event_callback,
base::OnceClosure disconnect_callback) { base::OnceClosure disconnect_callback) {
return nullptr; return nullptr;
} }
......
...@@ -17,6 +17,12 @@ namespace { ...@@ -17,6 +17,12 @@ namespace {
// any echoes are detected. // any echoes are detected.
const unsigned int kNumRemoteMousePositions = 50; const unsigned int kNumRemoteMousePositions = 50;
// The number of remote keypress events to record for the purpose of eliminating
// "echoes" detected by the local input detector. The value should be large
// enough to cope with the fact that multiple events might be injected before
// any echoes are detected.
const unsigned int kNumRemoteKeyPresses = 20;
// The number of milliseconds for which to block remote input when local input // The number of milliseconds for which to block remote input when local input
// is received. // is received.
const int64_t kRemoteBlockTimeoutMillis = 2000; const int64_t kRemoteBlockTimeoutMillis = 2000;
...@@ -61,10 +67,26 @@ bool RemoteInputFilter::LocalPointerMoved(const webrtc::DesktopVector& pos, ...@@ -61,10 +67,26 @@ bool RemoteInputFilter::LocalPointerMoved(const webrtc::DesktopVector& pos,
} }
} }
// Release all pressed buttons or keys, disable inputs, and note the time. LocalInputDetected();
return true;
}
bool RemoteInputFilter::LocalKeyPressed(uint32_t usb_keycode) {
// If local echo is expected and |usb_keycode| is the oldest unechoed injected
// keypress, then ignore it.
if (expect_local_echo_ && !injected_key_presses_.empty() &&
injected_key_presses_.front() == usb_keycode) {
injected_key_presses_.pop_front();
return false;
}
LocalInputDetected();
return true;
}
void RemoteInputFilter::LocalInputDetected() {
event_tracker_->ReleaseAll(); event_tracker_->ReleaseAll();
latest_local_input_time_ = base::TimeTicks::Now(); latest_local_input_time_ = base::TimeTicks::Now();
return true;
} }
void RemoteInputFilter::SetExpectLocalEcho(bool expect_local_echo) { void RemoteInputFilter::SetExpectLocalEcho(bool expect_local_echo) {
...@@ -76,6 +98,13 @@ void RemoteInputFilter::SetExpectLocalEcho(bool expect_local_echo) { ...@@ -76,6 +98,13 @@ void RemoteInputFilter::SetExpectLocalEcho(bool expect_local_echo) {
void RemoteInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) { void RemoteInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) {
if (ShouldIgnoreInput()) if (ShouldIgnoreInput())
return; return;
if (expect_local_echo_ && event.pressed() && event.has_usb_keycode()) {
injected_key_presses_.push_back(event.usb_keycode());
if (injected_key_presses_.size() > kNumRemoteKeyPresses) {
VLOG(1) << "Injected key press queue full.";
injected_key_presses_.clear();
}
}
event_tracker_->InjectKeyEvent(event); event_tracker_->InjectKeyEvent(event);
} }
......
...@@ -31,6 +31,12 @@ class RemoteInputFilter : public protocol::InputStub { ...@@ -31,6 +31,12 @@ class RemoteInputFilter : public protocol::InputStub {
// input was local, or false if it was rejected as an echo. // input was local, or false if it was rejected as an echo.
bool LocalPointerMoved(const webrtc::DesktopVector& pos, ui::EventType type); bool LocalPointerMoved(const webrtc::DesktopVector& pos, ui::EventType type);
// Informs the filter that a local keypress event has been detected. If the
// key does not correspond to one we injected then we assume that it is local,
// and block remote input for a short while. Returns true if the input was
// local, or false if it was rejected as an echo.
bool LocalKeyPressed(uint32_t usb_keycode);
// Informs the filter that injecting input causes an echo. // Informs the filter that injecting input causes an echo.
void SetExpectLocalEcho(bool expect_local_echo); void SetExpectLocalEcho(bool expect_local_echo);
...@@ -42,12 +48,15 @@ class RemoteInputFilter : public protocol::InputStub { ...@@ -42,12 +48,15 @@ class RemoteInputFilter : public protocol::InputStub {
private: private:
bool ShouldIgnoreInput() const; bool ShouldIgnoreInput() const;
void LocalInputDetected();
protocol::InputEventTracker* event_tracker_; protocol::InputEventTracker* event_tracker_;
// Queue of recently-injected mouse positions used to distinguish echoes of // Queue of recently-injected mouse positions and keypresses used to
// injected events from movements from a local input device. // distinguish echoes of injected events from movements from a local
// input device.
std::list<webrtc::DesktopVector> injected_mouse_positions_; std::list<webrtc::DesktopVector> injected_mouse_positions_;
std::list<uint32_t> injected_key_presses_;
// Time at which local input events were most recently observed. // Time at which local input events were most recently observed.
base::TimeTicks latest_local_input_time_; base::TimeTicks latest_local_input_time_;
......
...@@ -133,6 +133,59 @@ TEST(RemoteInputFilterTest, LocalEchosAndLocalActivity) { ...@@ -133,6 +133,59 @@ TEST(RemoteInputFilterTest, LocalEchosAndLocalActivity) {
} }
} }
// Verify that local keyboard input blocks activity.
TEST(RemoteInputFilterTest, LocalKeyPressEventBlocksInput) {
MockInputStub mock_stub;
InputEventTracker input_tracker(&mock_stub);
RemoteInputFilter input_filter(&input_tracker);
input_filter.LocalKeyPressed(0);
input_filter.InjectKeyEvent(UsbKeyEvent(1, true));
}
// Verify that local echoes of remote keyboard activity does not block input
TEST(RemoteInputFilterTest, LocalEchoOfKeyPressEventDoesNotBlockInput) {
MockInputStub mock_stub;
InputEventTracker input_tracker(&mock_stub);
RemoteInputFilter input_filter(&input_tracker);
EXPECT_CALL(mock_stub, InjectKeyEvent(_)).Times(4);
input_filter.InjectKeyEvent(UsbKeyEvent(1, true));
input_filter.InjectKeyEvent(UsbKeyEvent(1, false));
input_filter.LocalKeyPressed(1);
input_filter.InjectKeyEvent(UsbKeyEvent(2, true));
input_filter.InjectKeyEvent(UsbKeyEvent(2, false));
}
// Verify that local input matching remote keyboard activity that has already
// been discarded as an echo blocks input.
TEST(RemoteInputFilterTest, LocalKeyPressEventMatchingPreviousEchoBlocksInput) {
MockInputStub mock_stub;
InputEventTracker input_tracker(&mock_stub);
RemoteInputFilter input_filter(&input_tracker);
EXPECT_CALL(mock_stub, InjectKeyEvent(_)).Times(2);
input_filter.InjectKeyEvent(UsbKeyEvent(1, true));
input_filter.InjectKeyEvent(UsbKeyEvent(1, false));
input_filter.LocalKeyPressed(1);
input_filter.LocalKeyPressed(1);
input_filter.InjectKeyEvent(UsbKeyEvent(2, true));
input_filter.InjectKeyEvent(UsbKeyEvent(2, false));
}
// Verify that local input matching remote keyboard activity blocks input if
// local echo is not expected
TEST(RemoteInputFilterTest,
LocalDuplicateKeyPressEventBlocksInputIfEchoDisabled) {
MockInputStub mock_stub;
InputEventTracker input_tracker(&mock_stub);
RemoteInputFilter input_filter(&input_tracker);
input_filter.SetExpectLocalEcho(false);
EXPECT_CALL(mock_stub, InjectKeyEvent(_)).Times(2);
input_filter.InjectKeyEvent(UsbKeyEvent(1, true));
input_filter.InjectKeyEvent(UsbKeyEvent(1, false));
input_filter.LocalKeyPressed(1);
input_filter.InjectKeyEvent(UsbKeyEvent(2, true));
input_filter.InjectKeyEvent(UsbKeyEvent(2, false));
}
// Verify that local activity also causes buttons, keys, and touches to be // Verify that local activity also causes buttons, keys, and touches to be
// released. // released.
TEST(RemoteInputFilterTest, LocalActivityReleasesAll) { TEST(RemoteInputFilterTest, LocalActivityReleasesAll) {
......
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