File: local_keyboard_input_monitor_win.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (146 lines) | stat: -rw-r--r-- 5,523 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/input_monitor/local_keyboard_input_monitor.h"

#include <cstdint>
#include <memory>
#include <utility>

#include "base/functional/callback.h"
#include "base/location.h"
#include "base/memory/raw_ref.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/sequence_checker.h"
#include "base/task/bind_post_task.h"
#include "base/task/single_thread_task_runner.h"
#include "remoting/host/input_monitor/raw_input_handler.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "ui/events/keycodes/dom/keycode_converter.h"

namespace remoting {

namespace {

// From the HID Usage Tables specification.
const std::uint16_t kKeyboardUsage = 6;

// Handles Keyboard Raw Input events.  This class should be instantiated at-most
// once per process instance to prevent the events being silently dropped.
class KeyboardRawInputHandler : public RawInputHandler {
 public:
  explicit KeyboardRawInputHandler(
      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);

  KeyboardRawInputHandler(const KeyboardRawInputHandler&) = delete;
  KeyboardRawInputHandler& operator=(const KeyboardRawInputHandler&) = delete;

  ~KeyboardRawInputHandler() override;

  // RawInputHandler implementation.
  void OnInputEvent(const RAWINPUT& event) override;
};

KeyboardRawInputHandler::KeyboardRawInputHandler(
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
    : RawInputHandler(ui_task_runner, kKeyboardUsage) {}

KeyboardRawInputHandler::~KeyboardRawInputHandler() = default;

void KeyboardRawInputHandler::OnInputEvent(const RAWINPUT& event) {
  if (event.header.dwType == RIM_TYPEKEYBOARD &&
      event.header.hDevice != nullptr) {
    std::uint16_t vkey = event.data.keyboard.VKey;
    std::uint32_t scancode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
    std::uint32_t usb_keycode =
        ui::KeycodeConverter::NativeKeycodeToUsbKeycode(scancode);

    NotifyKeyboardInput(FROM_HERE, usb_keycode);
  }
}

class ScopedKeyboardInputMonitorWin : public LocalKeyboardInputMonitor,
                                      public RawInputHandler::Observer {
 public:
  explicit ScopedKeyboardInputMonitorWin(
      KeyboardRawInputHandler& raw_input_handler,
      LocalInputMonitor::KeyPressedCallback on_key_event_callback,
      base::OnceClosure disconnect_callback);
  ~ScopedKeyboardInputMonitorWin() override;

  // Observer implementation.
  void OnMouseMove(const webrtc::DesktopVector&, ui::EventType) override;
  void OnKeyboardInput(std::uint32_t usb_keycode) override;
  void OnError() override;

 private:
  base::raw_ref<KeyboardRawInputHandler> keyboard_raw_input_handler_;

  LocalInputMonitor::KeyPressedCallback on_key_event_callback_;
  base::OnceClosure disconnect_callback_;

  SEQUENCE_CHECKER(sequence_checker_);
};

ScopedKeyboardInputMonitorWin::ScopedKeyboardInputMonitorWin(
    KeyboardRawInputHandler& raw_input_handler,
    LocalInputMonitor::KeyPressedCallback on_key_event_callback,
    base::OnceClosure disconnect_callback)
    : keyboard_raw_input_handler_(raw_input_handler),
      on_key_event_callback_(std::move(on_key_event_callback)),
      disconnect_callback_(std::move(disconnect_callback)) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  keyboard_raw_input_handler_->AddObserver(this);
}

ScopedKeyboardInputMonitorWin::~ScopedKeyboardInputMonitorWin() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  keyboard_raw_input_handler_->RemoveObserver(this);
}

void ScopedKeyboardInputMonitorWin::OnKeyboardInput(uint32_t usb_keycode) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  on_key_event_callback_.Run(usb_keycode);
}

void ScopedKeyboardInputMonitorWin::OnMouseMove(
    const webrtc::DesktopVector& position,
    ui::EventType event_type) {
  NOTREACHED();
}

void ScopedKeyboardInputMonitorWin::OnError() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  std::move(disconnect_callback_).Run();
}

}  // namespace

std::unique_ptr<LocalKeyboardInputMonitor> LocalKeyboardInputMonitor::Create(
    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
    LocalInputMonitor::KeyPressedCallback on_key_event_callback,
    base::OnceClosure disconnect_callback) {
  // Ensure there is only one instance of KeyboardRawInputHandler because
  // Windows does not allow multiple windows to receive WM_INPUT messages for
  // the same raw input type in the same process.
  // Note: We reuse the initial |ui_task_runner| provided to init the handler,
  // this is reasonable as we just need a UI thread to run the core object on
  // and in practice, every invocation of this method passes the same
  // task_runner because it is retrieved via the ChromotingHostContext.
  static base::NoDestructor<KeyboardRawInputHandler> raw_input_handler{
      ui_task_runner};

  // Bind the callbacks to |caller_task_runner| to ensure they are executed on
  // the proper thread.
  return std::make_unique<ScopedKeyboardInputMonitorWin>(
      *raw_input_handler,
      base::BindPostTask(caller_task_runner, std::move(on_key_event_callback)),
      base::BindPostTask(caller_task_runner, std::move(disconnect_callback)));
}

}  // namespace remoting