blob: 7b5e2b581cb8358acd5ed696b89d6fe3d214bc63 [file] [log] [blame]
[email protected]86cbe6b2012-04-03 00:56:181// Copyright (c) 2012 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
5#include "remoting/protocol/input_event_tracker.h"
6
7#include "base/logging.h"
8#include "remoting/proto/event.pb.h"
9
10namespace remoting {
11namespace protocol {
12
Chris Watkins6fe52aa2017-11-28 03:24:0513InputEventTracker::InputEventTracker() = default;
jamiewalch14ece3d2016-03-04 23:46:1514
[email protected]86cbe6b2012-04-03 00:56:1815InputEventTracker::InputEventTracker(InputStub* input_stub)
jamiewalch14ece3d2016-03-04 23:46:1516 : input_stub_(input_stub) {
[email protected]86cbe6b2012-04-03 00:56:1817}
18
Chris Watkins6fe52aa2017-11-28 03:24:0519InputEventTracker::~InputEventTracker() = default;
[email protected]86cbe6b2012-04-03 00:56:1820
jamiewalchaadc22f2015-10-12 23:25:5021bool InputEventTracker::IsKeyPressed(ui::DomCode usb_keycode) const {
[email protected]83e6f582012-04-09 19:41:4622 return pressed_keys_.find(usb_keycode) != pressed_keys_.end();
23}
24
25int InputEventTracker::PressedKeyCount() const {
[email protected]f5e7c882012-09-11 01:52:1426 return pressed_keys_.size();
[email protected]83e6f582012-04-09 19:41:4627}
28
29void InputEventTracker::ReleaseAll() {
jamiewalch14ece3d2016-03-04 23:46:1530 DCHECK(input_stub_);
31
rkuroiwa0e68803f2015-02-26 19:41:4232 // Release all pressed keys.
jamiewalchaadc22f2015-10-12 23:25:5033 for (auto keycode : pressed_keys_) {
[email protected]83e6f582012-04-09 19:41:4634 KeyEvent event;
35 event.set_pressed(false);
jamiewalchaadc22f2015-10-12 23:25:5036 event.set_usb_keycode(static_cast<uint32_t>(keycode));
[email protected]83e6f582012-04-09 19:41:4637 input_stub_->InjectKeyEvent(event);
38 }
39 pressed_keys_.clear();
40
rkuroiwa0e68803f2015-02-26 19:41:4241 // Release all mouse buttons.
[email protected]83e6f582012-04-09 19:41:4642 for (int i = MouseEvent::BUTTON_UNDEFINED + 1;
43 i < MouseEvent::BUTTON_MAX; ++i) {
44 if (mouse_button_state_ & (1 << (i - 1))) {
45 MouseEvent mouse;
46
47 // TODO(wez): EventInjectors should cope with positionless events by
48 // using the current cursor position, and we wouldn't set position here.
49 mouse.set_x(mouse_pos_.x());
50 mouse.set_y(mouse_pos_.y());
51
52 mouse.set_button((MouseEvent::MouseButton)i);
53 mouse.set_button_down(false);
54 input_stub_->InjectMouseEvent(mouse);
55 }
56 }
57 mouse_button_state_ = 0;
rkuroiwa0e68803f2015-02-26 19:41:4258
59 // Cancel all active touch points.
60 if (!touch_point_ids_.empty()) {
61 TouchEvent cancel_all_touch_event;
62 cancel_all_touch_event.set_event_type(TouchEvent::TOUCH_POINT_CANCEL);
jamiewalchaadc22f2015-10-12 23:25:5063 for (uint32_t touch_point_id : touch_point_ids_) {
rkuroiwa0e68803f2015-02-26 19:41:4264 TouchEventPoint* point = cancel_all_touch_event.add_touch_points();
65 point->set_id(touch_point_id);
66 }
67 input_stub_->InjectTouchEvent(cancel_all_touch_event);
68 touch_point_ids_.clear();
69 }
70 DCHECK(touch_point_ids_.empty());
[email protected]83e6f582012-04-09 19:41:4671}
72
jamiewalch613d1622015-03-12 03:09:3973void InputEventTracker::ReleaseAllIfModifiersStuck(bool alt_expected,
74 bool ctrl_expected,
jamiewalchd09da9e2015-05-28 02:39:2475 bool os_expected,
jamiewalch613d1622015-03-12 03:09:3976 bool shift_expected) {
jamiewalch613d1622015-03-12 03:09:3977 bool alt_down =
jamiewalchaadc22f2015-10-12 23:25:5078 pressed_keys_.find(ui::DomCode::ALT_LEFT) != pressed_keys_.end() ||
79 pressed_keys_.find(ui::DomCode::ALT_RIGHT) != pressed_keys_.end();
jamiewalch613d1622015-03-12 03:09:3980 bool ctrl_down =
jamiewalchaadc22f2015-10-12 23:25:5081 pressed_keys_.find(ui::DomCode::CONTROL_LEFT) != pressed_keys_.end() ||
82 pressed_keys_.find(ui::DomCode::CONTROL_RIGHT) != pressed_keys_.end();
jamiewalchd09da9e2015-05-28 02:39:2483 bool os_down =
dtapuskaaf863af2016-04-21 14:33:5984 pressed_keys_.find(ui::DomCode::META_LEFT) != pressed_keys_.end() ||
85 pressed_keys_.find(ui::DomCode::META_RIGHT) != pressed_keys_.end();
jamiewalch613d1622015-03-12 03:09:3986 bool shift_down =
jamiewalchaadc22f2015-10-12 23:25:5087 pressed_keys_.find(ui::DomCode::SHIFT_LEFT) != pressed_keys_.end() ||
88 pressed_keys_.find(ui::DomCode::SHIFT_RIGHT) != pressed_keys_.end();
jamiewalch613d1622015-03-12 03:09:3989
90 if ((alt_down && !alt_expected) || (ctrl_down && !ctrl_expected) ||
jamiewalchd09da9e2015-05-28 02:39:2491 (os_down && !os_expected) || (shift_down && !shift_expected)) {
jamiewalch613d1622015-03-12 03:09:3992 ReleaseAll();
93 }
94}
95
[email protected]86cbe6b2012-04-03 00:56:1896void InputEventTracker::InjectKeyEvent(const KeyEvent& event) {
jamiewalch14ece3d2016-03-04 23:46:1597 DCHECK(input_stub_);
98
[email protected]5e3afcc2013-06-26 05:42:2799 // We don't need to track the keyboard lock states of key down events.
100 // Pressed keys will be released with |lock_states| set to 0.
101 // The lock states of auto generated key up events don't matter as long as
102 // we release all the pressed keys at blurring/disconnection time.
[email protected]83e6f582012-04-09 19:41:46103 if (event.has_pressed()) {
104 if (event.has_usb_keycode()) {
105 if (event.pressed()) {
jamiewalchaadc22f2015-10-12 23:25:50106 pressed_keys_.insert(static_cast<ui::DomCode>(event.usb_keycode()));
[email protected]83e6f582012-04-09 19:41:46107 } else {
jamiewalchaadc22f2015-10-12 23:25:50108 pressed_keys_.erase(static_cast<ui::DomCode>(event.usb_keycode()));
[email protected]83e6f582012-04-09 19:41:46109 }
[email protected]fa8c7292012-04-04 17:26:37110 }
[email protected]86cbe6b2012-04-03 00:56:18111 }
112 input_stub_->InjectKeyEvent(event);
113}
114
[email protected]529bbd12014-03-27 20:25:39115void InputEventTracker::InjectTextEvent(const TextEvent& event) {
jamiewalch14ece3d2016-03-04 23:46:15116 DCHECK(input_stub_);
[email protected]529bbd12014-03-27 20:25:39117 input_stub_->InjectTextEvent(event);
118}
119
[email protected]86cbe6b2012-04-03 00:56:18120void InputEventTracker::InjectMouseEvent(const MouseEvent& event) {
jamiewalch14ece3d2016-03-04 23:46:15121 DCHECK(input_stub_);
122
[email protected]86cbe6b2012-04-03 00:56:18123 if (event.has_x() && event.has_y()) {
[email protected]e59d6592013-09-25 22:16:21124 mouse_pos_ = webrtc::DesktopVector(event.x(), event.y());
[email protected]86cbe6b2012-04-03 00:56:18125 }
126 if (event.has_button() && event.has_button_down()) {
127 // Button values are defined in remoting/proto/event.proto.
128 if (event.button() >= 1 && event.button() < MouseEvent::BUTTON_MAX) {
jamiewalchaadc22f2015-10-12 23:25:50129 uint32_t button_change = 1 << (event.button() - 1);
[email protected]86cbe6b2012-04-03 00:56:18130 if (event.button_down()) {
131 mouse_button_state_ |= button_change;
132 } else {
133 mouse_button_state_ &= ~button_change;
134 }
135 }
136 }
137 input_stub_->InjectMouseEvent(event);
138}
139
rkuroiwa0e68803f2015-02-26 19:41:42140void InputEventTracker::InjectTouchEvent(const TouchEvent& event) {
jamiewalch14ece3d2016-03-04 23:46:15141 DCHECK(input_stub_);
rkuroiwa0e68803f2015-02-26 19:41:42142 // We only need the IDs to cancel all touch points in ReleaseAll(). Other
143 // fields do not have to be tracked here as long as the host keeps track of
144 // them.
145 switch (event.event_type()) {
146 case TouchEvent::TOUCH_POINT_START:
147 for (const TouchEventPoint& touch_point : event.touch_points()) {
148 DCHECK(touch_point_ids_.find(touch_point.id()) ==
149 touch_point_ids_.end());
150 touch_point_ids_.insert(touch_point.id());
151 }
152 break;
153 case TouchEvent::TOUCH_POINT_END:
154 case TouchEvent::TOUCH_POINT_CANCEL:
155 for (const TouchEventPoint& touch_point : event.touch_points()) {
156 DCHECK(touch_point_ids_.find(touch_point.id()) !=
157 touch_point_ids_.end());
158 touch_point_ids_.erase(touch_point.id());
159 }
160 break;
161 default:
162 break;
163 }
164 input_stub_->InjectTouchEvent(event);
165}
166
[email protected]86cbe6b2012-04-03 00:56:18167} // namespace protocol
168} // namespace remoting