Fix mouse warp with 2x displays
[chromium-blink-merge.git] / remoting / host / input_injector_chromeos.cc
blob8fa2ea2e9d27be2359b218ca41ad1b7f5315eb3e
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/input_injector_chromeos.h"
7 #include <set>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/location.h"
12 #include "remoting/host/chromeos/point_transformer.h"
13 #include "remoting/host/clipboard.h"
14 #include "remoting/proto/internal.pb.h"
15 #include "ui/events/keycodes/dom/dom_code.h"
16 #include "ui/events/keycodes/dom/keycode_converter.h"
17 #include "ui/ozone/public/input_controller.h"
18 #include "ui/ozone/public/ozone_platform.h"
19 #include "ui/ozone/public/system_input_injector.h"
21 namespace remoting {
23 using protocol::ClipboardEvent;
24 using protocol::KeyEvent;
25 using protocol::MouseEvent;
26 using protocol::TextEvent;
27 using protocol::TouchEvent;
29 namespace {
31 ui::EventFlags MouseButtonToUIFlags(MouseEvent::MouseButton button) {
32 switch (button) {
33 case MouseEvent::BUTTON_LEFT:
34 return ui::EF_LEFT_MOUSE_BUTTON;
35 case MouseEvent::BUTTON_RIGHT:
36 return ui::EF_RIGHT_MOUSE_BUTTON;
37 case MouseEvent::BUTTON_MIDDLE:
38 return ui::EF_MIDDLE_MOUSE_BUTTON;
39 default:
40 NOTREACHED();
41 return ui::EF_NONE;
45 } // namespace
47 // This class is run exclusively on the UI thread of the browser process.
48 class InputInjectorChromeos::Core {
49 public:
50 Core();
52 // Mirrors the public InputInjectorChromeos interface.
53 void InjectClipboardEvent(const ClipboardEvent& event);
54 void InjectKeyEvent(const KeyEvent& event);
55 void InjectTextEvent(const TextEvent& event);
56 void InjectMouseEvent(const MouseEvent& event);
57 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard);
59 private:
60 scoped_ptr<ui::SystemInputInjector> delegate_;
61 scoped_ptr<Clipboard> clipboard_;
63 // Used to rotate the input coordinates appropriately based on the current
64 // display rotation settings.
65 scoped_ptr<PointTransformer> point_transformer_;
67 DISALLOW_COPY_AND_ASSIGN(Core);
70 InputInjectorChromeos::Core::Core() {
73 void InputInjectorChromeos::Core::InjectClipboardEvent(
74 const ClipboardEvent& event) {
75 clipboard_->InjectClipboardEvent(event);
78 void InputInjectorChromeos::Core::InjectKeyEvent(const KeyEvent& event) {
79 DCHECK(event.has_pressed());
80 DCHECK(event.has_usb_keycode());
82 ui::DomCode dom_code =
83 ui::KeycodeConverter::UsbKeycodeToDomCode(event.usb_keycode());
85 // Ignore events which can't be mapped.
86 if (dom_code != ui::DomCode::NONE) {
87 delegate_->InjectKeyEvent(dom_code, event.pressed(),
88 true /* suppress_auto_repeat */);
92 void InputInjectorChromeos::Core::InjectTextEvent(const TextEvent& event) {
93 // Chrome OS only supports It2Me, which is not supported on mobile clients, so
94 // we don't need to implement text events.
95 NOTIMPLEMENTED();
98 void InputInjectorChromeos::Core::InjectMouseEvent(const MouseEvent& event) {
99 if (event.has_button() && event.has_button_down()) {
100 delegate_->InjectMouseButton(MouseButtonToUIFlags(event.button()),
101 event.button_down());
102 } else if (event.has_wheel_delta_y() || event.has_wheel_delta_x()) {
103 delegate_->InjectMouseWheel(event.wheel_delta_x(), event.wheel_delta_y());
104 } else {
105 DCHECK(event.has_x() && event.has_y());
106 delegate_->MoveCursorTo(point_transformer_->ToScreenCoordinates(
107 gfx::PointF(event.x(), event.y())));
111 void InputInjectorChromeos::Core::Start(
112 scoped_ptr<protocol::ClipboardStub> client_clipboard) {
113 ui::OzonePlatform* ozone_platform = ui::OzonePlatform::GetInstance();
114 delegate_ = ozone_platform->CreateSystemInputInjector();
115 DCHECK(delegate_);
117 // Implemented by remoting::ClipboardAura.
118 clipboard_ = Clipboard::Create();
119 clipboard_->Start(client_clipboard.Pass());
120 point_transformer_.reset(new PointTransformer());
123 InputInjectorChromeos::InputInjectorChromeos(
124 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
125 : input_task_runner_(task_runner) {
126 core_.reset(new Core());
129 InputInjectorChromeos::~InputInjectorChromeos() {
130 input_task_runner_->DeleteSoon(FROM_HERE, core_.release());
133 void InputInjectorChromeos::InjectClipboardEvent(const ClipboardEvent& event) {
134 input_task_runner_->PostTask(
135 FROM_HERE, base::Bind(&Core::InjectClipboardEvent,
136 base::Unretained(core_.get()), event));
139 void InputInjectorChromeos::InjectKeyEvent(const KeyEvent& event) {
140 input_task_runner_->PostTask(
141 FROM_HERE,
142 base::Bind(&Core::InjectKeyEvent, base::Unretained(core_.get()), event));
145 void InputInjectorChromeos::InjectTextEvent(const TextEvent& event) {
146 input_task_runner_->PostTask(
147 FROM_HERE,
148 base::Bind(&Core::InjectTextEvent, base::Unretained(core_.get()), event));
151 void InputInjectorChromeos::InjectMouseEvent(const MouseEvent& event) {
152 input_task_runner_->PostTask(
153 FROM_HERE, base::Bind(&Core::InjectMouseEvent,
154 base::Unretained(core_.get()), event));
157 void InputInjectorChromeos::InjectTouchEvent(const TouchEvent& event) {
158 NOTIMPLEMENTED() << "Raw touch event injection not implemented for ChromeOS.";
161 void InputInjectorChromeos::Start(
162 scoped_ptr<protocol::ClipboardStub> client_clipboard) {
163 input_task_runner_->PostTask(
164 FROM_HERE, base::Bind(&Core::Start, base::Unretained(core_.get()),
165 base::Passed(&client_clipboard)));
168 // static
169 scoped_ptr<InputInjector> InputInjector::Create(
170 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
171 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
172 // The Ozone input injector must be called on the UI task runner of the
173 // browser process.
174 return make_scoped_ptr(new InputInjectorChromeos(ui_task_runner));
177 // static
178 bool InputInjector::SupportsTouchEvents() {
179 return false;
182 } // namespace remoting