OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "remoting/host/event_executor.h" | 5 #include "remoting/host/input_injector.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
14 #include "remoting/base/util.h" | 14 #include "remoting/base/util.h" |
15 #include "remoting/host/clipboard.h" | 15 #include "remoting/host/clipboard.h" |
16 #include "remoting/proto/event.pb.h" | 16 #include "remoting/proto/event.pb.h" |
17 // SkSize.h assumes that stdint.h-style types are already defined. | 17 // SkSize.h assumes that stdint.h-style types are already defined. |
18 #include "third_party/skia/include/core/SkTypes.h" | 18 #include "third_party/skia/include/core/SkTypes.h" |
19 #include "third_party/skia/include/core/SkSize.h" | 19 #include "third_party/skia/include/core/SkSize.h" |
20 | 20 |
21 namespace remoting { | 21 namespace remoting { |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 using protocol::ClipboardEvent; | 25 using protocol::ClipboardEvent; |
26 using protocol::KeyEvent; | 26 using protocol::KeyEvent; |
27 using protocol::MouseEvent; | 27 using protocol::MouseEvent; |
28 | 28 |
29 // USB to XKB keycode map table. | 29 // USB to XKB keycode map table. |
30 #define USB_KEYMAP(usb, xkb, win, mac) {usb, win} | 30 #define USB_KEYMAP(usb, xkb, win, mac) {usb, win} |
31 #include "ui/base/keycodes/usb_keycode_map.h" | 31 #include "ui/base/keycodes/usb_keycode_map.h" |
32 #undef USB_KEYMAP | 32 #undef USB_KEYMAP |
33 | 33 |
34 // A class to generate events on Windows. | 34 // A class to generate events on Windows. |
35 class EventExecutorWin : public EventExecutor { | 35 class InputInjectorWin : public InputInjector { |
36 public: | 36 public: |
37 EventExecutorWin(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 37 InputInjectorWin(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
38 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); | 38 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); |
39 virtual ~EventExecutorWin(); | 39 virtual ~InputInjectorWin(); |
40 | 40 |
41 // ClipboardStub interface. | 41 // ClipboardStub interface. |
42 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; | 42 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; |
43 | 43 |
44 // InputStub interface. | 44 // InputStub interface. |
45 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; | 45 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; |
46 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; | 46 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; |
47 | 47 |
48 // EventExecutor interface. | 48 // InputInjector interface. |
49 virtual void Start( | 49 virtual void Start( |
50 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; | 50 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; |
51 | 51 |
52 private: | 52 private: |
53 // The actual implementation resides in EventExecutorWin::Core class. | 53 // The actual implementation resides in InputInjectorWin::Core class. |
54 class Core : public base::RefCountedThreadSafe<Core> { | 54 class Core : public base::RefCountedThreadSafe<Core> { |
55 public: | 55 public: |
56 Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 56 Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
57 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); | 57 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); |
58 | 58 |
59 // Mirrors the ClipboardStub interface. | 59 // Mirrors the ClipboardStub interface. |
60 void InjectClipboardEvent(const ClipboardEvent& event); | 60 void InjectClipboardEvent(const ClipboardEvent& event); |
61 | 61 |
62 // Mirrors the InputStub interface. | 62 // Mirrors the InputStub interface. |
63 void InjectKeyEvent(const KeyEvent& event); | 63 void InjectKeyEvent(const KeyEvent& event); |
64 void InjectMouseEvent(const MouseEvent& event); | 64 void InjectMouseEvent(const MouseEvent& event); |
65 | 65 |
66 // Mirrors the EventExecutor interface. | 66 // Mirrors the InputInjector interface. |
67 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard); | 67 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard); |
68 | 68 |
69 void Stop(); | 69 void Stop(); |
70 | 70 |
71 private: | 71 private: |
72 friend class base::RefCountedThreadSafe<Core>; | 72 friend class base::RefCountedThreadSafe<Core>; |
73 virtual ~Core(); | 73 virtual ~Core(); |
74 | 74 |
75 void HandleKey(const KeyEvent& event); | 75 void HandleKey(const KeyEvent& event); |
76 void HandleMouse(const MouseEvent& event); | 76 void HandleMouse(const MouseEvent& event); |
77 | 77 |
78 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 78 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
79 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; | 79 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
80 scoped_ptr<Clipboard> clipboard_; | 80 scoped_ptr<Clipboard> clipboard_; |
81 | 81 |
82 DISALLOW_COPY_AND_ASSIGN(Core); | 82 DISALLOW_COPY_AND_ASSIGN(Core); |
83 }; | 83 }; |
84 | 84 |
85 scoped_refptr<Core> core_; | 85 scoped_refptr<Core> core_; |
86 | 86 |
87 DISALLOW_COPY_AND_ASSIGN(EventExecutorWin); | 87 DISALLOW_COPY_AND_ASSIGN(InputInjectorWin); |
88 }; | 88 }; |
89 | 89 |
90 EventExecutorWin::EventExecutorWin( | 90 InputInjectorWin::InputInjectorWin( |
91 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 91 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
92 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 92 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
93 core_ = new Core(main_task_runner, ui_task_runner); | 93 core_ = new Core(main_task_runner, ui_task_runner); |
94 } | 94 } |
95 | 95 |
96 EventExecutorWin::~EventExecutorWin() { | 96 InputInjectorWin::~InputInjectorWin() { |
97 core_->Stop(); | 97 core_->Stop(); |
98 } | 98 } |
99 | 99 |
100 void EventExecutorWin::InjectClipboardEvent(const ClipboardEvent& event) { | 100 void InputInjectorWin::InjectClipboardEvent(const ClipboardEvent& event) { |
101 core_->InjectClipboardEvent(event); | 101 core_->InjectClipboardEvent(event); |
102 } | 102 } |
103 | 103 |
104 void EventExecutorWin::InjectKeyEvent(const KeyEvent& event) { | 104 void InputInjectorWin::InjectKeyEvent(const KeyEvent& event) { |
105 core_->InjectKeyEvent(event); | 105 core_->InjectKeyEvent(event); |
106 } | 106 } |
107 | 107 |
108 void EventExecutorWin::InjectMouseEvent(const MouseEvent& event) { | 108 void InputInjectorWin::InjectMouseEvent(const MouseEvent& event) { |
109 core_->InjectMouseEvent(event); | 109 core_->InjectMouseEvent(event); |
110 } | 110 } |
111 | 111 |
112 void EventExecutorWin::Start( | 112 void InputInjectorWin::Start( |
113 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 113 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
114 core_->Start(client_clipboard.Pass()); | 114 core_->Start(client_clipboard.Pass()); |
115 } | 115 } |
116 | 116 |
117 EventExecutorWin::Core::Core( | 117 InputInjectorWin::Core::Core( |
118 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 118 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
119 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) | 119 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) |
120 : main_task_runner_(main_task_runner), | 120 : main_task_runner_(main_task_runner), |
121 ui_task_runner_(ui_task_runner), | 121 ui_task_runner_(ui_task_runner), |
122 clipboard_(Clipboard::Create()) { | 122 clipboard_(Clipboard::Create()) { |
123 } | 123 } |
124 | 124 |
125 void EventExecutorWin::Core::InjectClipboardEvent(const ClipboardEvent& event) { | 125 void InputInjectorWin::Core::InjectClipboardEvent(const ClipboardEvent& event) { |
126 if (!ui_task_runner_->BelongsToCurrentThread()) { | 126 if (!ui_task_runner_->BelongsToCurrentThread()) { |
127 ui_task_runner_->PostTask( | 127 ui_task_runner_->PostTask( |
128 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event)); | 128 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event)); |
129 return; | 129 return; |
130 } | 130 } |
131 | 131 |
132 // |clipboard_| will ignore unknown MIME-types, and verify the data's format. | 132 // |clipboard_| will ignore unknown MIME-types, and verify the data's format. |
133 clipboard_->InjectClipboardEvent(event); | 133 clipboard_->InjectClipboardEvent(event); |
134 } | 134 } |
135 | 135 |
136 void EventExecutorWin::Core::InjectKeyEvent(const KeyEvent& event) { | 136 void InputInjectorWin::Core::InjectKeyEvent(const KeyEvent& event) { |
137 if (!main_task_runner_->BelongsToCurrentThread()) { | 137 if (!main_task_runner_->BelongsToCurrentThread()) { |
138 main_task_runner_->PostTask(FROM_HERE, | 138 main_task_runner_->PostTask(FROM_HERE, |
139 base::Bind(&Core::InjectKeyEvent, this, event)); | 139 base::Bind(&Core::InjectKeyEvent, this, event)); |
140 return; | 140 return; |
141 } | 141 } |
142 | 142 |
143 HandleKey(event); | 143 HandleKey(event); |
144 } | 144 } |
145 | 145 |
146 void EventExecutorWin::Core::InjectMouseEvent(const MouseEvent& event) { | 146 void InputInjectorWin::Core::InjectMouseEvent(const MouseEvent& event) { |
147 if (!main_task_runner_->BelongsToCurrentThread()) { | 147 if (!main_task_runner_->BelongsToCurrentThread()) { |
148 main_task_runner_->PostTask( | 148 main_task_runner_->PostTask( |
149 FROM_HERE, base::Bind(&Core::InjectMouseEvent, this, event)); | 149 FROM_HERE, base::Bind(&Core::InjectMouseEvent, this, event)); |
150 return; | 150 return; |
151 } | 151 } |
152 | 152 |
153 HandleMouse(event); | 153 HandleMouse(event); |
154 } | 154 } |
155 | 155 |
156 void EventExecutorWin::Core::Start( | 156 void InputInjectorWin::Core::Start( |
157 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 157 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
158 if (!ui_task_runner_->BelongsToCurrentThread()) { | 158 if (!ui_task_runner_->BelongsToCurrentThread()) { |
159 ui_task_runner_->PostTask( | 159 ui_task_runner_->PostTask( |
160 FROM_HERE, | 160 FROM_HERE, |
161 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); | 161 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); |
162 return; | 162 return; |
163 } | 163 } |
164 | 164 |
165 clipboard_->Start(client_clipboard.Pass()); | 165 clipboard_->Start(client_clipboard.Pass()); |
166 } | 166 } |
167 | 167 |
168 void EventExecutorWin::Core::Stop() { | 168 void InputInjectorWin::Core::Stop() { |
169 if (!ui_task_runner_->BelongsToCurrentThread()) { | 169 if (!ui_task_runner_->BelongsToCurrentThread()) { |
170 ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); | 170 ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); |
171 return; | 171 return; |
172 } | 172 } |
173 | 173 |
174 clipboard_->Stop(); | 174 clipboard_->Stop(); |
175 } | 175 } |
176 | 176 |
177 EventExecutorWin::Core::~Core() { | 177 InputInjectorWin::Core::~Core() { |
178 } | 178 } |
179 | 179 |
180 void EventExecutorWin::Core::HandleKey(const KeyEvent& event) { | 180 void InputInjectorWin::Core::HandleKey(const KeyEvent& event) { |
181 // HostEventDispatcher should filter events missing the pressed field. | 181 // HostEventDispatcher should filter events missing the pressed field. |
182 if (!event.has_pressed() || !event.has_usb_keycode()) | 182 if (!event.has_pressed() || !event.has_usb_keycode()) |
183 return; | 183 return; |
184 | 184 |
185 // Reset the system idle suspend timeout. | 185 // Reset the system idle suspend timeout. |
186 SetThreadExecutionState(ES_SYSTEM_REQUIRED); | 186 SetThreadExecutionState(ES_SYSTEM_REQUIRED); |
187 | 187 |
188 int scancode = UsbKeycodeToNativeKeycode(event.usb_keycode()); | 188 int scancode = UsbKeycodeToNativeKeycode(event.usb_keycode()); |
189 | 189 |
190 VLOG(3) << "Converting USB keycode: " << std::hex << event.usb_keycode() | 190 VLOG(3) << "Converting USB keycode: " << std::hex << event.usb_keycode() |
(...skipping 17 matching lines...) Expand all Loading... |
208 // high-order values we should see are 0xE0 or 0xE1. The extended bit usually | 208 // high-order values we should see are 0xE0 or 0xE1. The extended bit usually |
209 // distinguishes keys with the same meaning, e.g. left & right shift. | 209 // distinguishes keys with the same meaning, e.g. left & right shift. |
210 input.ki.wScan = scancode & 0xFF; | 210 input.ki.wScan = scancode & 0xFF; |
211 if ((scancode & 0xFF00) != 0x0000) | 211 if ((scancode & 0xFF00) != 0x0000) |
212 input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; | 212 input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; |
213 | 213 |
214 if (SendInput(1, &input, sizeof(INPUT)) == 0) | 214 if (SendInput(1, &input, sizeof(INPUT)) == 0) |
215 LOG_GETLASTERROR(ERROR) << "Failed to inject a key event"; | 215 LOG_GETLASTERROR(ERROR) << "Failed to inject a key event"; |
216 } | 216 } |
217 | 217 |
218 void EventExecutorWin::Core::HandleMouse(const MouseEvent& event) { | 218 void InputInjectorWin::Core::HandleMouse(const MouseEvent& event) { |
219 // Reset the system idle suspend timeout. | 219 // Reset the system idle suspend timeout. |
220 SetThreadExecutionState(ES_SYSTEM_REQUIRED); | 220 SetThreadExecutionState(ES_SYSTEM_REQUIRED); |
221 | 221 |
222 // TODO(garykac) Collapse mouse (x,y) and button events into a single | 222 // TODO(garykac) Collapse mouse (x,y) and button events into a single |
223 // input event when possible. | 223 // input event when possible. |
224 if (event.has_x() && event.has_y()) { | 224 if (event.has_x() && event.has_y()) { |
225 int x = event.x(); | 225 int x = event.x(); |
226 int y = event.y(); | 226 int y = event.y(); |
227 | 227 |
228 INPUT input; | 228 INPUT input; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; | 302 down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; |
303 } | 303 } |
304 | 304 |
305 if (SendInput(1, &button_event, sizeof(INPUT)) == 0) | 305 if (SendInput(1, &button_event, sizeof(INPUT)) == 0) |
306 LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse button event"; | 306 LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse button event"; |
307 } | 307 } |
308 } | 308 } |
309 | 309 |
310 } // namespace | 310 } // namespace |
311 | 311 |
312 scoped_ptr<EventExecutor> EventExecutor::Create( | 312 scoped_ptr<InputInjector> InputInjector::Create( |
313 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 313 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
314 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 314 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
315 return scoped_ptr<EventExecutor>( | 315 return scoped_ptr<InputInjector>( |
316 new EventExecutorWin(main_task_runner, ui_task_runner)); | 316 new InputInjectorWin(main_task_runner, ui_task_runner)); |
317 } | 317 } |
318 | 318 |
319 } // namespace remoting | 319 } // namespace remoting |
OLD | NEW |