[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 1 | // 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 | |||||
10 | namespace remoting { | ||||
11 | namespace protocol { | ||||
12 | |||||
Chris Watkins | 6fe52aa | 2017-11-28 03:24:05 | [diff] [blame] | 13 | InputEventTracker::InputEventTracker() = default; |
jamiewalch | 14ece3d | 2016-03-04 23:46:15 | [diff] [blame] | 14 | |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 15 | InputEventTracker::InputEventTracker(InputStub* input_stub) |
jamiewalch | 14ece3d | 2016-03-04 23:46:15 | [diff] [blame] | 16 | : input_stub_(input_stub) { |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 17 | } |
18 | |||||
Chris Watkins | 6fe52aa | 2017-11-28 03:24:05 | [diff] [blame] | 19 | InputEventTracker::~InputEventTracker() = default; |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 20 | |
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 21 | bool InputEventTracker::IsKeyPressed(ui::DomCode usb_keycode) const { |
[email protected] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 22 | return pressed_keys_.find(usb_keycode) != pressed_keys_.end(); |
23 | } | ||||
24 | |||||
25 | int InputEventTracker::PressedKeyCount() const { | ||||
[email protected] | f5e7c88 | 2012-09-11 01:52:14 | [diff] [blame] | 26 | return pressed_keys_.size(); |
[email protected] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 27 | } |
28 | |||||
29 | void InputEventTracker::ReleaseAll() { | ||||
jamiewalch | 14ece3d | 2016-03-04 23:46:15 | [diff] [blame] | 30 | DCHECK(input_stub_); |
31 | |||||
rkuroiwa | 0e68803f | 2015-02-26 19:41:42 | [diff] [blame] | 32 | // Release all pressed keys. |
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 33 | for (auto keycode : pressed_keys_) { |
[email protected] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 34 | KeyEvent event; |
35 | event.set_pressed(false); | ||||
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 36 | event.set_usb_keycode(static_cast<uint32_t>(keycode)); |
[email protected] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 37 | input_stub_->InjectKeyEvent(event); |
38 | } | ||||
39 | pressed_keys_.clear(); | ||||
40 | |||||
rkuroiwa | 0e68803f | 2015-02-26 19:41:42 | [diff] [blame] | 41 | // Release all mouse buttons. |
[email protected] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 42 | 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; | ||||
rkuroiwa | 0e68803f | 2015-02-26 19:41:42 | [diff] [blame] | 58 | |
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); | ||||
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 63 | for (uint32_t touch_point_id : touch_point_ids_) { |
rkuroiwa | 0e68803f | 2015-02-26 19:41:42 | [diff] [blame] | 64 | 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] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 71 | } |
72 | |||||
jamiewalch | 613d162 | 2015-03-12 03:09:39 | [diff] [blame] | 73 | void InputEventTracker::ReleaseAllIfModifiersStuck(bool alt_expected, |
74 | bool ctrl_expected, | ||||
jamiewalch | d09da9e | 2015-05-28 02:39:24 | [diff] [blame] | 75 | bool os_expected, |
jamiewalch | 613d162 | 2015-03-12 03:09:39 | [diff] [blame] | 76 | bool shift_expected) { |
jamiewalch | 613d162 | 2015-03-12 03:09:39 | [diff] [blame] | 77 | bool alt_down = |
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 78 | pressed_keys_.find(ui::DomCode::ALT_LEFT) != pressed_keys_.end() || |
79 | pressed_keys_.find(ui::DomCode::ALT_RIGHT) != pressed_keys_.end(); | ||||
jamiewalch | 613d162 | 2015-03-12 03:09:39 | [diff] [blame] | 80 | bool ctrl_down = |
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 81 | pressed_keys_.find(ui::DomCode::CONTROL_LEFT) != pressed_keys_.end() || |
82 | pressed_keys_.find(ui::DomCode::CONTROL_RIGHT) != pressed_keys_.end(); | ||||
jamiewalch | d09da9e | 2015-05-28 02:39:24 | [diff] [blame] | 83 | bool os_down = |
dtapuska | af863af | 2016-04-21 14:33:59 | [diff] [blame] | 84 | pressed_keys_.find(ui::DomCode::META_LEFT) != pressed_keys_.end() || |
85 | pressed_keys_.find(ui::DomCode::META_RIGHT) != pressed_keys_.end(); | ||||
jamiewalch | 613d162 | 2015-03-12 03:09:39 | [diff] [blame] | 86 | bool shift_down = |
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 87 | pressed_keys_.find(ui::DomCode::SHIFT_LEFT) != pressed_keys_.end() || |
88 | pressed_keys_.find(ui::DomCode::SHIFT_RIGHT) != pressed_keys_.end(); | ||||
jamiewalch | 613d162 | 2015-03-12 03:09:39 | [diff] [blame] | 89 | |
90 | if ((alt_down && !alt_expected) || (ctrl_down && !ctrl_expected) || | ||||
jamiewalch | d09da9e | 2015-05-28 02:39:24 | [diff] [blame] | 91 | (os_down && !os_expected) || (shift_down && !shift_expected)) { |
jamiewalch | 613d162 | 2015-03-12 03:09:39 | [diff] [blame] | 92 | ReleaseAll(); |
93 | } | ||||
94 | } | ||||
95 | |||||
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 96 | void InputEventTracker::InjectKeyEvent(const KeyEvent& event) { |
jamiewalch | 14ece3d | 2016-03-04 23:46:15 | [diff] [blame] | 97 | DCHECK(input_stub_); |
98 | |||||
[email protected] | 5e3afcc | 2013-06-26 05:42:27 | [diff] [blame] | 99 | // 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] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 103 | if (event.has_pressed()) { |
104 | if (event.has_usb_keycode()) { | ||||
105 | if (event.pressed()) { | ||||
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 106 | pressed_keys_.insert(static_cast<ui::DomCode>(event.usb_keycode())); |
[email protected] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 107 | } else { |
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 108 | pressed_keys_.erase(static_cast<ui::DomCode>(event.usb_keycode())); |
[email protected] | 83e6f58 | 2012-04-09 19:41:46 | [diff] [blame] | 109 | } |
[email protected] | fa8c729 | 2012-04-04 17:26:37 | [diff] [blame] | 110 | } |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 111 | } |
112 | input_stub_->InjectKeyEvent(event); | ||||
113 | } | ||||
114 | |||||
[email protected] | 529bbd1 | 2014-03-27 20:25:39 | [diff] [blame] | 115 | void InputEventTracker::InjectTextEvent(const TextEvent& event) { |
jamiewalch | 14ece3d | 2016-03-04 23:46:15 | [diff] [blame] | 116 | DCHECK(input_stub_); |
[email protected] | 529bbd1 | 2014-03-27 20:25:39 | [diff] [blame] | 117 | input_stub_->InjectTextEvent(event); |
118 | } | ||||
119 | |||||
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 120 | void InputEventTracker::InjectMouseEvent(const MouseEvent& event) { |
jamiewalch | 14ece3d | 2016-03-04 23:46:15 | [diff] [blame] | 121 | DCHECK(input_stub_); |
122 | |||||
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 123 | if (event.has_x() && event.has_y()) { |
[email protected] | e59d659 | 2013-09-25 22:16:21 | [diff] [blame] | 124 | mouse_pos_ = webrtc::DesktopVector(event.x(), event.y()); |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 125 | } |
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) { | ||||
jamiewalch | aadc22f | 2015-10-12 23:25:50 | [diff] [blame] | 129 | uint32_t button_change = 1 << (event.button() - 1); |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 130 | 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 | |||||
rkuroiwa | 0e68803f | 2015-02-26 19:41:42 | [diff] [blame] | 140 | void InputEventTracker::InjectTouchEvent(const TouchEvent& event) { |
jamiewalch | 14ece3d | 2016-03-04 23:46:15 | [diff] [blame] | 141 | DCHECK(input_stub_); |
rkuroiwa | 0e68803f | 2015-02-26 19:41:42 | [diff] [blame] | 142 | // 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] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 167 | } // namespace protocol |
168 | } // namespace remoting |