File: local_mouse_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 (164 lines) | stat: -rw-r--r-- 5,913 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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// 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 <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/local_pointer_input_monitor.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 kMouseUsage = 2;

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

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

  ~MouseRawInputHandler() override;

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

 private:
  webrtc::DesktopVector mouse_position_;
};

MouseRawInputHandler::MouseRawInputHandler(
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
    : RawInputHandler(ui_task_runner, kMouseUsage) {}

MouseRawInputHandler::~MouseRawInputHandler() = default;

void MouseRawInputHandler::OnInputEvent(const RAWINPUT& event) {
  // Notify the observer about mouse events generated locally. Remote (injected)
  // mouse events do not specify a device handle (based on observed behavior).
  if (event.header.dwType != RIM_TYPEMOUSE || event.header.hDevice == nullptr) {
    return;
  }

  POINT position;
  if (!GetCursorPos(&position)) {
    position.x = 0;
    position.y = 0;
  }
  webrtc::DesktopVector new_position(position.x, position.y);

  // Ignore the event if the cursor position or button states have not changed.
  // Note: If GetCursorPos fails above, we err on the safe side and treat it
  // like a movement.
  if (mouse_position_.equals(new_position) && !event.data.mouse.usButtonFlags &&
      !new_position.is_zero()) {
    return;
  }

  mouse_position_ = new_position;

  NotifyMouseMove(FROM_HERE, new_position);
}

// Note that this class does not detect touch input and so is named accordingly.
class ScopedMouseInputMonitorWin : public LocalPointerInputMonitor,
                                   public RawInputHandler::Observer {
 public:
  explicit ScopedMouseInputMonitorWin(
      MouseRawInputHandler& raw_input_handler,
      LocalInputMonitor::PointerMoveCallback on_mouse_move,
      base::OnceClosure disconnect_callback);
  ~ScopedMouseInputMonitorWin() 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<MouseRawInputHandler> raw_input_handler_;

  LocalInputMonitor::PointerMoveCallback on_mouse_move_;
  base::OnceClosure disconnect_callback_;

  SEQUENCE_CHECKER(sequence_checker_);
};

ScopedMouseInputMonitorWin::ScopedMouseInputMonitorWin(
    MouseRawInputHandler& raw_input_handler,
    LocalInputMonitor::PointerMoveCallback on_mouse_move,
    base::OnceClosure disconnect_callback)
    : raw_input_handler_(raw_input_handler),
      on_mouse_move_(std::move(on_mouse_move)),
      disconnect_callback_(std::move(disconnect_callback)) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  raw_input_handler_->AddObserver(this);
}

ScopedMouseInputMonitorWin::~ScopedMouseInputMonitorWin() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  raw_input_handler_->RemoveObserver(this);
}

void ScopedMouseInputMonitorWin::OnMouseMove(
    const webrtc::DesktopVector& position,
    ui::EventType event_type) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  on_mouse_move_.Run(position, event_type);
}

void ScopedMouseInputMonitorWin::OnKeyboardInput(uint32_t usb_keycode) {
  NOTREACHED();
}

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

}  // namespace

std::unique_ptr<LocalPointerInputMonitor> LocalPointerInputMonitor::Create(
    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
    LocalInputMonitor::PointerMoveCallback on_mouse_move,
    base::OnceClosure disconnect_callback) {
  // Ensure there is only one instance of MouseRawInputHandler 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<MouseRawInputHandler> 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<ScopedMouseInputMonitorWin>(
      *raw_input_handler,
      base::BindPostTask(caller_task_runner, std::move(on_mouse_move)),
      base::BindPostTask(caller_task_runner, std::move(disconnect_callback)));
}

}  // namespace remoting