local_keyboard_input_monitor_win.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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_keyboard_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 "ui/events/keycodes/dom/keycode_converter.h"
  13. namespace remoting {
  14. namespace {
  15. // From the HID Usage Tables specification.
  16. const USHORT kGenericDesktopPage = 1;
  17. const USHORT kKeyboardUsage = 6;
  18. class KeyboardRawInputHandlerWin
  19. : public LocalInputMonitorWin::RawInputHandler {
  20. public:
  21. KeyboardRawInputHandlerWin(
  22. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  23. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
  24. LocalInputMonitor::KeyPressedCallback on_key_event_callback,
  25. base::OnceClosure disconnect_callback);
  26. KeyboardRawInputHandlerWin(const KeyboardRawInputHandlerWin&) = delete;
  27. KeyboardRawInputHandlerWin& operator=(const KeyboardRawInputHandlerWin&) =
  28. delete;
  29. ~KeyboardRawInputHandlerWin() override;
  30. // LocalInputMonitorWin::RawInputHandler implementation.
  31. bool Register(HWND hwnd) override;
  32. void Unregister() override;
  33. void OnInputEvent(const RAWINPUT* input) override;
  34. void OnError() override;
  35. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
  36. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
  37. LocalInputMonitor::KeyPressedCallback on_key_event_callback_;
  38. base::OnceClosure disconnect_callback_;
  39. // Tracks whether the instance is registered to receive raw input events.
  40. bool registered_ = false;
  41. };
  42. KeyboardRawInputHandlerWin::KeyboardRawInputHandlerWin(
  43. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  44. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
  45. LocalInputMonitor::KeyPressedCallback on_key_event_callback,
  46. base::OnceClosure disconnect_callback)
  47. : caller_task_runner_(caller_task_runner),
  48. ui_task_runner_(ui_task_runner),
  49. on_key_event_callback_(std::move(on_key_event_callback)),
  50. disconnect_callback_(std::move(disconnect_callback)) {}
  51. KeyboardRawInputHandlerWin::~KeyboardRawInputHandlerWin() {
  52. DCHECK(!registered_);
  53. }
  54. bool KeyboardRawInputHandlerWin::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 = kKeyboardUsage;
  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 KeyboardRawInputHandlerWin::Unregister() {
  70. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  71. RAWINPUTDEVICE device = {0};
  72. device.dwFlags = RIDEV_REMOVE;
  73. device.usUsagePage = kGenericDesktopPage;
  74. device.usUsage = kKeyboardUsage;
  75. device.hwndTarget = nullptr;
  76. // The error is harmless, ignore it.
  77. RegisterRawInputDevices(&device, 1, sizeof(device));
  78. registered_ = false;
  79. }
  80. void KeyboardRawInputHandlerWin::OnInputEvent(const RAWINPUT* input) {
  81. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  82. if (input->header.dwType == RIM_TYPEKEYBOARD &&
  83. input->header.hDevice != nullptr) {
  84. USHORT vkey = input->data.keyboard.VKey;
  85. UINT scancode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
  86. uint32_t usb_keycode =
  87. ui::KeycodeConverter::NativeKeycodeToUsbKeycode(scancode);
  88. caller_task_runner_->PostTask(
  89. FROM_HERE, base::BindOnce(on_key_event_callback_, usb_keycode));
  90. }
  91. }
  92. void KeyboardRawInputHandlerWin::OnError() {
  93. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  94. if (disconnect_callback_) {
  95. caller_task_runner_->PostTask(FROM_HERE, std::move(disconnect_callback_));
  96. }
  97. }
  98. class LocalKeyboardInputMonitorWin : public LocalKeyboardInputMonitor {
  99. public:
  100. explicit LocalKeyboardInputMonitorWin(
  101. std::unique_ptr<LocalInputMonitorWin> local_input_monitor);
  102. ~LocalKeyboardInputMonitorWin() override;
  103. private:
  104. std::unique_ptr<LocalInputMonitorWin> local_input_monitor_;
  105. };
  106. LocalKeyboardInputMonitorWin::LocalKeyboardInputMonitorWin(
  107. std::unique_ptr<LocalInputMonitorWin> local_input_monitor)
  108. : local_input_monitor_(std::move(local_input_monitor)) {}
  109. LocalKeyboardInputMonitorWin::~LocalKeyboardInputMonitorWin() = default;
  110. } // namespace
  111. std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create(
  112. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  113. scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
  114. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
  115. LocalInputMonitor::KeyPressedCallback on_key_event_callback,
  116. base::OnceClosure disconnect_callback) {
  117. auto raw_input_handler = std::make_unique<KeyboardRawInputHandlerWin>(
  118. caller_task_runner, ui_task_runner, std::move(on_key_event_callback),
  119. std::move(disconnect_callback));
  120. return std::make_unique<LocalKeyboardInputMonitorWin>(
  121. LocalInputMonitorWin::Create(caller_task_runner, ui_task_runner,
  122. std::move(raw_input_handler)));
  123. }
  124. } // namespace remoting