local_mouse_input_monitor_win.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright 2018 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.
  4. #include "remoting/host/input_monitor/local_pointer_input_monitor.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/callback.h"
  8. #include "base/location.h"
  9. #include "base/logging.h"
  10. #include "base/task/single_thread_task_runner.h"
  11. #include "remoting/host/input_monitor/local_input_monitor_win.h"
  12. #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
  13. #include "ui/events/event.h"
  14. namespace remoting {
  15. namespace {
  16. // From the HID Usage Tables specification.
  17. const USHORT kGenericDesktopPage = 1;
  18. const USHORT kMouseUsage = 2;
  19. class MouseRawInputHandlerWin : public LocalInputMonitorWin::RawInputHandler {
  20. public:
  21. MouseRawInputHandlerWin(
  22. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  23. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
  24. LocalInputMonitor::PointerMoveCallback on_mouse_move,
  25. base::OnceClosure disconnect_callback);
  26. MouseRawInputHandlerWin(const MouseRawInputHandlerWin&) = delete;
  27. MouseRawInputHandlerWin& operator=(const MouseRawInputHandlerWin&) = delete;
  28. ~MouseRawInputHandlerWin() override;
  29. // LocalInputMonitorWin::RawInputHandler implementation.
  30. bool Register(HWND hwnd) override;
  31. void Unregister() override;
  32. void OnInputEvent(const RAWINPUT* input) override;
  33. void OnError() override;
  34. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
  35. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
  36. LocalInputMonitor::PointerMoveCallback on_mouse_move_;
  37. base::OnceClosure disconnect_callback_;
  38. webrtc::DesktopVector mouse_position_;
  39. // Tracks whether the instance is registered to receive raw input events.
  40. bool registered_ = false;
  41. };
  42. MouseRawInputHandlerWin::MouseRawInputHandlerWin(
  43. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  44. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
  45. LocalInputMonitor::PointerMoveCallback on_mouse_move,
  46. base::OnceClosure disconnect_callback)
  47. : caller_task_runner_(caller_task_runner),
  48. ui_task_runner_(ui_task_runner),
  49. on_mouse_move_(std::move(on_mouse_move)),
  50. disconnect_callback_(std::move(disconnect_callback)) {}
  51. MouseRawInputHandlerWin::~MouseRawInputHandlerWin() {
  52. DCHECK(!registered_);
  53. }
  54. bool MouseRawInputHandlerWin::Register(HWND hwnd) {
  55. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  56. // Register to receive raw keyboard input.
  57. RAWINPUTDEVICE device = {0};
  58. device.dwFlags = RIDEV_INPUTSINK;
  59. device.usUsagePage = kGenericDesktopPage;
  60. device.usUsage = kMouseUsage;
  61. device.hwndTarget = hwnd;
  62. if (!RegisterRawInputDevices(&device, 1, sizeof(device))) {
  63. PLOG(ERROR) << "RegisterRawInputDevices() failed";
  64. return false;
  65. }
  66. registered_ = true;
  67. return true;
  68. }
  69. void MouseRawInputHandlerWin::Unregister() {
  70. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  71. RAWINPUTDEVICE device = {0};
  72. device.dwFlags = RIDEV_REMOVE;
  73. device.usUsagePage = kGenericDesktopPage;
  74. device.usUsage = kMouseUsage;
  75. device.hwndTarget = nullptr;
  76. // The error is harmless, ignore it.
  77. RegisterRawInputDevices(&device, 1, sizeof(device));
  78. registered_ = false;
  79. }
  80. void MouseRawInputHandlerWin::OnInputEvent(const RAWINPUT* input) {
  81. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  82. // Notify the observer about mouse events generated locally. Remote (injected)
  83. // mouse events do not specify a device handle (based on observed behavior).
  84. if (input->header.dwType != RIM_TYPEMOUSE ||
  85. input->header.hDevice == nullptr) {
  86. return;
  87. }
  88. POINT position;
  89. if (!GetCursorPos(&position)) {
  90. position.x = 0;
  91. position.y = 0;
  92. }
  93. webrtc::DesktopVector new_position(position.x, position.y);
  94. // Ignore the event if the cursor position or button states have not changed.
  95. // Note: If GetCursorPos fails above, we err on the safe side and treat it
  96. // like a movement.
  97. if (mouse_position_.equals(new_position) &&
  98. !input->data.mouse.usButtonFlags && !new_position.is_zero()) {
  99. return;
  100. }
  101. mouse_position_ = new_position;
  102. caller_task_runner_->PostTask(
  103. FROM_HERE, base::BindOnce(on_mouse_move_, std::move(new_position),
  104. ui::ET_MOUSE_MOVED));
  105. }
  106. void MouseRawInputHandlerWin::OnError() {
  107. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  108. if (disconnect_callback_) {
  109. caller_task_runner_->PostTask(FROM_HERE, std::move(disconnect_callback_));
  110. }
  111. }
  112. // Note that this class does not detect touch input and so is named accordingly.
  113. class LocalMouseInputMonitorWin : public LocalPointerInputMonitor {
  114. public:
  115. explicit LocalMouseInputMonitorWin(
  116. std::unique_ptr<LocalInputMonitorWin> local_input_monitor);
  117. ~LocalMouseInputMonitorWin() override;
  118. private:
  119. std::unique_ptr<LocalInputMonitorWin> local_input_monitor_;
  120. };
  121. LocalMouseInputMonitorWin::LocalMouseInputMonitorWin(
  122. std::unique_ptr<LocalInputMonitorWin> local_input_monitor)
  123. : local_input_monitor_(std::move(local_input_monitor)) {}
  124. LocalMouseInputMonitorWin::~LocalMouseInputMonitorWin() = default;
  125. } // namespace
  126. std::unique_ptr<LocalPointerInputMonitor> LocalPointerInputMonitor::Create(
  127. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  128. scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
  129. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
  130. LocalInputMonitor::PointerMoveCallback on_mouse_move,
  131. base::OnceClosure disconnect_callback) {
  132. auto raw_input_handler = std::make_unique<MouseRawInputHandlerWin>(
  133. caller_task_runner, ui_task_runner, std::move(on_mouse_move),
  134. std::move(disconnect_callback));
  135. return std::make_unique<LocalMouseInputMonitorWin>(
  136. LocalInputMonitorWin::Create(caller_task_runner, ui_task_runner,
  137. std::move(raw_input_handler)));
  138. }
  139. } // namespace remoting