OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/input_injector.h" | 5 #include "remoting/host/input_injector.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <X11/extensions/XInput.h> | 9 #include <X11/extensions/XInput.h> |
10 #include <X11/extensions/XTest.h> | 10 #include <X11/extensions/XTest.h> |
11 #include <X11/Xlib.h> | 11 #include <X11/Xlib.h> |
12 #include <X11/XKBlib.h> | 12 #include <X11/XKBlib.h> |
13 #include <X11/keysym.h> | |
13 #undef Status // Xlib.h #defines this, which breaks protobuf headers. | 14 #undef Status // Xlib.h #defines this, which breaks protobuf headers. |
14 | 15 |
15 #include <set> | 16 #include <set> |
16 #include <utility> | 17 #include <utility> |
17 | 18 |
18 #include "base/bind.h" | 19 #include "base/bind.h" |
19 #include "base/compiler_specific.h" | 20 #include "base/compiler_specific.h" |
20 #include "base/location.h" | 21 #include "base/location.h" |
21 #include "base/macros.h" | 22 #include "base/macros.h" |
22 #include "base/memory/ptr_util.h" | 23 #include "base/memory/ptr_util.h" |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 | 115 |
115 // Queries whether keyboard auto-repeat is globally enabled. This is used | 116 // Queries whether keyboard auto-repeat is globally enabled. This is used |
116 // to decide whether to temporarily disable then restore this setting. If | 117 // to decide whether to temporarily disable then restore this setting. If |
117 // auto-repeat has already been disabled, this class should leave it | 118 // auto-repeat has already been disabled, this class should leave it |
118 // untouched. | 119 // untouched. |
119 bool IsAutoRepeatEnabled(); | 120 bool IsAutoRepeatEnabled(); |
120 | 121 |
121 // Enables or disables keyboard auto-repeat globally. | 122 // Enables or disables keyboard auto-repeat globally. |
122 void SetAutoRepeatEnabled(bool enabled); | 123 void SetAutoRepeatEnabled(bool enabled); |
123 | 124 |
125 // Sets the keyboard lock states to those provided. | |
126 void SetLockStates(uint32_t states); | |
127 | |
124 void InjectScrollWheelClicks(int button, int count); | 128 void InjectScrollWheelClicks(int button, int count); |
125 // Compensates for global button mappings and resets the XTest device | 129 // Compensates for global button mappings and resets the XTest device |
126 // mapping. | 130 // mapping. |
127 void InitMouseButtonMap(); | 131 void InitMouseButtonMap(); |
128 int MouseButtonToX11ButtonNumber(MouseEvent::MouseButton button); | 132 int MouseButtonToX11ButtonNumber(MouseEvent::MouseButton button); |
129 int HorizontalScrollWheelToX11ButtonNumber(int dx); | 133 int HorizontalScrollWheelToX11ButtonNumber(int dx); |
130 int VerticalScrollWheelToX11ButtonNumber(int dy); | 134 int VerticalScrollWheelToX11ButtonNumber(int dy); |
131 | 135 |
132 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 136 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
133 | 137 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 if (event.pressed()) { | 273 if (event.pressed()) { |
270 if (pressed_keys_.find(keycode) != pressed_keys_.end()) { | 274 if (pressed_keys_.find(keycode) != pressed_keys_.end()) { |
271 // Ignore repeats for modifier keys. | 275 // Ignore repeats for modifier keys. |
272 if (IsModifierKey(static_cast<ui::DomCode>(event.usb_keycode()))) | 276 if (IsModifierKey(static_cast<ui::DomCode>(event.usb_keycode()))) |
273 return; | 277 return; |
274 // Key is already held down, so lift the key up to ensure this repeated | 278 // Key is already held down, so lift the key up to ensure this repeated |
275 // press takes effect. | 279 // press takes effect. |
276 XTestFakeKeyEvent(display_, keycode, False, CurrentTime); | 280 XTestFakeKeyEvent(display_, keycode, False, CurrentTime); |
277 } | 281 } |
278 | 282 |
283 if (event.has_lock_states()) { | |
284 SetLockStates(event.lock_states()); | |
285 } | |
286 | |
279 if (pressed_keys_.empty()) { | 287 if (pressed_keys_.empty()) { |
280 // Disable auto-repeat, if necessary, to avoid triggering auto-repeat | 288 // Disable auto-repeat, if necessary, to avoid triggering auto-repeat |
281 // if network congestion delays the key-up event from the client. | 289 // if network congestion delays the key-up event from the client. |
282 saved_auto_repeat_enabled_ = IsAutoRepeatEnabled(); | 290 saved_auto_repeat_enabled_ = IsAutoRepeatEnabled(); |
283 if (saved_auto_repeat_enabled_) | 291 if (saved_auto_repeat_enabled_) |
284 SetAutoRepeatEnabled(false); | 292 SetAutoRepeatEnabled(false); |
285 } | 293 } |
286 pressed_keys_.insert(keycode); | 294 pressed_keys_.insert(keycode); |
287 } else { | 295 } else { |
288 pressed_keys_.erase(keycode); | 296 pressed_keys_.erase(keycode); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 } | 348 } |
341 return state.global_auto_repeat == AutoRepeatModeOn; | 349 return state.global_auto_repeat == AutoRepeatModeOn; |
342 } | 350 } |
343 | 351 |
344 void InputInjectorX11::Core::SetAutoRepeatEnabled(bool mode) { | 352 void InputInjectorX11::Core::SetAutoRepeatEnabled(bool mode) { |
345 XKeyboardControl control; | 353 XKeyboardControl control; |
346 control.auto_repeat_mode = mode ? AutoRepeatModeOn : AutoRepeatModeOff; | 354 control.auto_repeat_mode = mode ? AutoRepeatModeOn : AutoRepeatModeOff; |
347 XChangeKeyboardControl(display_, KBAutoRepeatMode, &control); | 355 XChangeKeyboardControl(display_, KBAutoRepeatMode, &control); |
348 } | 356 } |
349 | 357 |
358 void InputInjectorX11::Core::SetLockStates(uint32_t states) { | |
359 unsigned int caps_lock_mask = XkbKeysymToModifiers(display_, XK_Caps_Lock); | |
360 unsigned int num_lock_mask = XkbKeysymToModifiers(display_, XK_Num_Lock); | |
361 unsigned int lock_values = 0; | |
362 if (states & protocol::KeyEvent::LOCK_STATES_CAPSLOCK) { | |
363 lock_values |= caps_lock_mask; | |
364 } | |
365 if (states & protocol::KeyEvent::LOCK_STATES_NUMLOCK) { | |
366 lock_values |= num_lock_mask; | |
367 } | |
368 XkbLockModifiers(display_, XkbUseCoreKbd, caps_lock_mask | num_lock_mask, | |
369 lock_values); | |
rkjnsn
2017/04/25 19:25:03
We could check the existing states first instead o
Jamie
2017/04/25 20:15:57
I think this is fine. The documentation suggests t
| |
370 } | |
371 | |
350 void InputInjectorX11::Core::InjectScrollWheelClicks(int button, int count) { | 372 void InputInjectorX11::Core::InjectScrollWheelClicks(int button, int count) { |
351 if (button < 0) { | 373 if (button < 0) { |
352 LOG(WARNING) << "Ignoring unmapped scroll wheel button"; | 374 LOG(WARNING) << "Ignoring unmapped scroll wheel button"; |
353 return; | 375 return; |
354 } | 376 } |
355 for (int i = 0; i < count; i++) { | 377 for (int i = 0; i < count; i++) { |
356 // Generate a button-down and a button-up to simulate a wheel click. | 378 // Generate a button-down and a button-up to simulate a wheel click. |
357 XTestFakeButtonEvent(display_, button, true, CurrentTime); | 379 XTestFakeButtonEvent(display_, button, true, CurrentTime); |
358 XTestFakeButtonEvent(display_, button, false, CurrentTime); | 380 XTestFakeButtonEvent(display_, button, false, CurrentTime); |
359 } | 381 } |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 return nullptr; | 625 return nullptr; |
604 return std::move(injector); | 626 return std::move(injector); |
605 } | 627 } |
606 | 628 |
607 // static | 629 // static |
608 bool InputInjector::SupportsTouchEvents() { | 630 bool InputInjector::SupportsTouchEvents() { |
609 return false; | 631 return false; |
610 } | 632 } |
611 | 633 |
612 } // namespace remoting | 634 } // namespace remoting |
OLD | NEW |