OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_linux.h" | 5 #include "remoting/host/event_executor_linux.h" |
6 | 6 |
7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
8 #include <X11/keysym.h> | 8 #include <X11/keysym.h> |
9 #include <X11/extensions/XTest.h> | 9 #include <X11/extensions/XTest.h> |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop_proxy.h" | |
13 #include "base/task.h" | |
12 #include "remoting/proto/internal.pb.h" | 14 #include "remoting/proto/internal.pb.h" |
13 | 15 |
14 namespace remoting { | 16 namespace remoting { |
15 | 17 |
16 static int MouseButtonToX11ButtonNumber(MouseButton button) { | 18 static int MouseButtonToX11ButtonNumber(MouseButton button) { |
17 switch (button) { | 19 switch (button) { |
18 case MouseButtonLeft: | 20 case MouseButtonLeft: |
19 return 1; | 21 return 1; |
20 | 22 |
21 case MouseButtonRight: | 23 case MouseButtonRight: |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 | 195 |
194 return kPepperToX11Keysym[keycode]; | 196 return kPepperToX11Keysym[keycode]; |
195 } | 197 } |
196 | 198 |
197 class EventExecutorLinuxPimpl { | 199 class EventExecutorLinuxPimpl { |
198 public: | 200 public: |
199 explicit EventExecutorLinuxPimpl(EventExecutorLinux* executor); | 201 explicit EventExecutorLinuxPimpl(EventExecutorLinux* executor); |
200 ~EventExecutorLinuxPimpl(); | 202 ~EventExecutorLinuxPimpl(); |
201 | 203 |
202 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? | 204 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? |
203 | 205 void HandleMouse(const MouseEvent* message); |
204 void HandleInputEvent(ChromotingClientMessage* message); | 206 void HandleKey(const KeyEvent* key_event); |
205 | 207 |
206 private: | 208 private: |
207 void HandleMouseSetPosition(const MouseSetPositionEvent& position_event); | 209 void HandleMouseSetPosition(const MouseSetPositionEvent& position_event); |
208 void HandleMouseMove(const MouseMoveEvent& move_event); | 210 void HandleMouseMove(const MouseMoveEvent& move_event); |
209 void HandleMouseWheel(const MouseWheelEvent& wheel_event); | 211 void HandleMouseWheel(const MouseWheelEvent& wheel_event); |
210 void HandleMouseButtonDown(const MouseDownEvent& mouse_down_event); | 212 void HandleMouseButtonDown(const MouseDownEvent& mouse_down_event); |
211 void HandleMouseButtonUp(const MouseUpEvent& mouse_up_event); | 213 void HandleMouseButtonUp(const MouseUpEvent& mouse_up_event); |
212 void HandleKey(const KeyEvent& key_event); | |
213 void DeinitXlib(); | 214 void DeinitXlib(); |
214 | 215 |
215 // Reference to containing class so we can access friend functions. | 216 // Reference to containing class so we can access friend functions. |
216 // Not owned. | 217 // Not owned. |
217 EventExecutorLinux* executor_; | 218 EventExecutorLinux* executor_; |
218 | 219 |
219 // X11 graphics context. | 220 // X11 graphics context. |
220 Display* display_; | 221 Display* display_; |
221 GC gc_; | 222 GC gc_; |
222 Window root_window_; | 223 Window root_window_; |
223 int width_; | 224 int width_; |
224 int height_; | 225 int height_; |
225 | 226 |
226 int test_event_base_; | 227 int test_event_base_; |
227 int test_error_base_; | 228 int test_error_base_; |
228 }; | 229 }; |
229 | 230 |
230 EventExecutorLinux::EventExecutorLinux(Capturer* capturer) | |
231 : EventExecutor(capturer), | |
232 pimpl_(new EventExecutorLinuxPimpl(this)) { | |
233 CHECK(pimpl_->Init()); | |
234 } | |
235 | |
236 EventExecutorLinux::~EventExecutorLinux() { | |
237 } | |
238 | |
239 void EventExecutorLinux::HandleInputEvent(ChromotingClientMessage* message) { | |
240 pimpl_->HandleInputEvent(message); | |
241 } | |
242 | |
243 EventExecutorLinuxPimpl::EventExecutorLinuxPimpl(EventExecutorLinux* executor) | 231 EventExecutorLinuxPimpl::EventExecutorLinuxPimpl(EventExecutorLinux* executor) |
244 : executor_(executor), | 232 : executor_(executor), |
245 display_(NULL), | 233 display_(NULL), |
246 gc_(NULL), | 234 gc_(NULL), |
247 root_window_(BadValue), | 235 root_window_(BadValue), |
248 width_(0), | 236 width_(0), |
249 height_(0) { | 237 height_(0) { |
250 } | 238 } |
251 | 239 |
252 EventExecutorLinuxPimpl::~EventExecutorLinuxPimpl() { | 240 EventExecutorLinuxPimpl::~EventExecutorLinuxPimpl() { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 DeinitXlib(); | 283 DeinitXlib(); |
296 return false; | 284 return false; |
297 } | 285 } |
298 | 286 |
299 width_ = root_attr.width; | 287 width_ = root_attr.width; |
300 height_ = root_attr.height; | 288 height_ = root_attr.height; |
301 | 289 |
302 return true; | 290 return true; |
303 } | 291 } |
304 | 292 |
305 void EventExecutorLinuxPimpl::HandleInputEvent( | 293 void EventExecutorLinuxPimpl::HandleMouse( |
306 ChromotingClientMessage* message) { | 294 const MouseEvent* mouse_event) { |
307 if (message->has_mouse_set_position_event()) { | 295 if (mouse_event->has_set_position()) { |
308 HandleMouseSetPosition(message->mouse_set_position_event()); | 296 HandleMouseSetPosition(mouse_event->set_position()); |
309 } else if (message->has_mouse_move_event()) { | 297 } else if (mouse_event->has_wheel()) { |
310 HandleMouseMove(message->mouse_move_event()); | 298 HandleMouseWheel(mouse_event->wheel()); |
311 } else if (message->has_mouse_wheel_event()) { | 299 } else if (mouse_event->has_down()) { |
312 HandleMouseWheel(message->mouse_wheel_event()); | 300 HandleMouseButtonDown(mouse_event->down()); |
313 } else if (message->has_mouse_down_event()) { | 301 } else if (mouse_event->has_up()) { |
314 HandleMouseButtonDown(message->mouse_down_event()); | 302 HandleMouseButtonUp(mouse_event->up()); |
315 } else if (message->has_mouse_up_event()) { | |
316 HandleMouseButtonUp(message->mouse_up_event()); | |
317 } else if (message->has_key_event()) { | |
318 HandleKey(message->key_event()); | |
319 } | 303 } |
320 delete message; | |
321 } | 304 } |
322 | 305 |
323 void EventExecutorLinuxPimpl::HandleMouseSetPosition( | 306 void EventExecutorLinuxPimpl::HandleMouseSetPosition( |
324 const MouseSetPositionEvent& position_event) { | 307 const MouseSetPositionEvent& position_event) { |
325 if (position_event.x() < 0 || position_event.y() < 0 || | 308 if (position_event.x() < 0 || position_event.y() < 0 || |
326 position_event.x() > width_ || position_event.y() > height_) { | 309 position_event.x() > width_ || position_event.y() > height_) { |
327 // A misbehaving client may send these. Drop events that are out of range. | 310 // A misbehaving client may send these. Drop events that are out of range. |
328 // TODO(ajwong): How can we log this sanely? We don't want to DOS the server | 311 // TODO(ajwong): How can we log this sanely? We don't want to DOS the server |
329 // with a misbehaving client by logging like crazy. | 312 // with a misbehaving client by logging like crazy. |
330 return; | 313 return; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 LOG(WARNING) << "Ignoring unknown button type: " | 352 LOG(WARNING) << "Ignoring unknown button type: " |
370 << mouse_up_event.button(); | 353 << mouse_up_event.button(); |
371 return; | 354 return; |
372 } | 355 } |
373 | 356 |
374 VLOG(3) << "Button " << mouse_up_event.button() | 357 VLOG(3) << "Button " << mouse_up_event.button() |
375 << " received, sending up " << button_number; | 358 << " received, sending up " << button_number; |
376 XTestFakeButtonEvent(display_, button_number, False, CurrentTime); | 359 XTestFakeButtonEvent(display_, button_number, False, CurrentTime); |
377 } | 360 } |
378 | 361 |
379 void EventExecutorLinuxPimpl::HandleKey(const KeyEvent& key_event) { | 362 void EventExecutorLinuxPimpl::HandleKey(const KeyEvent* key_event) { |
380 // TODO(ajwong): This will only work for QWERTY keyboards. | 363 // TODO(ajwong): This will only work for QWERTY keyboards. |
381 int keysym = ChromotocolKeycodeToX11Keysym(key_event.key()); | 364 int keysym = ChromotocolKeycodeToX11Keysym(key_event->key()); |
382 | 365 |
383 if (keysym == -1) { | 366 if (keysym == -1) { |
384 LOG(WARNING) << "Ignoring unknown key: " << key_event.key(); | 367 LOG(WARNING) << "Ignoring unknown key: " << key_event->key(); |
385 return; | 368 return; |
386 } | 369 } |
387 | 370 |
388 // Translate the keysym into a keycode understandable by the X display. | 371 // Translate the keysym into a keycode understandable by the X display. |
389 int keycode = XKeysymToKeycode(display_, keysym); | 372 int keycode = XKeysymToKeycode(display_, keysym); |
390 if (keycode == 0) { | 373 if (keycode == 0) { |
391 LOG(WARNING) << "Ignoring undefined keysym: " << keysym | 374 LOG(WARNING) << "Ignoring undefined keysym: " << keysym |
392 << " for key: " << key_event.key(); | 375 << " for key: " << key_event->key(); |
393 return; | 376 return; |
394 } | 377 } |
395 | 378 |
396 VLOG(3) << "Got pepper key: " << key_event.key() | 379 VLOG(3) << "Got pepper key: " << key_event->key() |
397 << " sending keysym: " << keysym | 380 << " sending keysym: " << keysym |
398 << " to keycode: " << keycode; | 381 << " to keycode: " << keycode; |
399 XTestFakeKeyEvent(display_, keycode, key_event.pressed(), CurrentTime); | 382 XTestFakeKeyEvent(display_, keycode, key_event->pressed(), CurrentTime); |
400 } | 383 } |
401 | 384 |
402 void EventExecutorLinuxPimpl::DeinitXlib() { | 385 void EventExecutorLinuxPimpl::DeinitXlib() { |
403 // TODO(ajwong): We should expose a "close" or "shutdown" method. | 386 // TODO(ajwong): We should expose a "close" or "shutdown" method. |
404 if (gc_) { | 387 if (gc_) { |
405 if (!XFreeGC(display_, gc_)) { | 388 if (!XFreeGC(display_, gc_)) { |
406 LOG(ERROR) << "Unable to free Xlib GC"; | 389 LOG(ERROR) << "Unable to free Xlib GC"; |
407 } | 390 } |
408 gc_ = NULL; | 391 gc_ = NULL; |
409 } | 392 } |
410 | 393 |
411 if (display_) { | 394 if (display_) { |
412 if (!XCloseDisplay(display_)) { | 395 if (!XCloseDisplay(display_)) { |
413 LOG(ERROR) << "Unable to close the Xlib Display."; | 396 LOG(ERROR) << "Unable to close the Xlib Display."; |
414 } | 397 } |
415 display_ = NULL; | 398 display_ = NULL; |
416 } | 399 } |
417 } | 400 } |
418 | 401 |
402 EventExecutorLinux::EventExecutorLinux( | |
403 scoped_refptr<base::MessageLoopProxy> message_loop, Capturer* capturer) | |
404 : message_loop_(message_loop), | |
405 capturer_(capturer), | |
406 pimpl_(new EventExecutorLinuxPimpl(this)) { | |
407 CHECK(pimpl_->Init()); | |
408 } | |
409 | |
410 EventExecutorLinux::~EventExecutorLinux() { | |
411 } | |
412 | |
413 void EventExecutorLinux::InjectKeyEvent(const KeyEvent* event, Task* done) { | |
414 if (!message_loop_->BelongsToCurrentThread()) { | |
415 message_loop_->PostTask( | |
416 FROM_HERE, | |
417 NewRunnableMethod(this, &EventExecutorLinux::InjectKeyEvent, | |
418 event, done)); | |
419 return; | |
420 } | |
421 pimpl_->HandleKey(event); | |
422 done->Run(); | |
423 delete done; | |
424 } | |
425 | |
426 void EventExecutorLinux::InjectMouseEvent(const MouseEvent* event, | |
427 Task* done) { | |
428 if (!message_loop_->BelongsToCurrentThread()) { | |
429 message_loop_->PostTask( | |
430 FROM_HERE, | |
431 NewRunnableMethod(this, &EventExecutorLinux::InjectMouseEvent, | |
432 event, done)); | |
433 return; | |
434 } | |
435 pimpl_->HandleMouse(event); | |
436 done->Run(); | |
437 delete done; | |
438 } | |
439 | |
419 } // namespace remoting | 440 } // namespace remoting |
441 | |
442 DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::EventExecutorLinux); | |
awong
2010/11/12 01:40:10
This needs to go in the header file.
| |
OLD | NEW |