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 #undef Status // Xlib.h #defines this, which breaks protobuf headers. | 13 #undef Status // Xlib.h #defines this, which breaks protobuf headers. |
14 | 14 |
15 #include <set> | 15 #include <set> |
16 #include <utility> | 16 #include <utility> |
17 | 17 |
18 #include "base/bind.h" | 18 #include "base/bind.h" |
19 #include "base/compiler_specific.h" | 19 #include "base/compiler_specific.h" |
20 #include "base/location.h" | 20 #include "base/location.h" |
21 #include "base/macros.h" | 21 #include "base/macros.h" |
| 22 #include "base/memory/ptr_util.h" |
22 #include "base/single_thread_task_runner.h" | 23 #include "base/single_thread_task_runner.h" |
23 #include "base/strings/utf_string_conversion_utils.h" | 24 #include "base/strings/utf_string_conversion_utils.h" |
24 #include "build/build_config.h" | 25 #include "build/build_config.h" |
25 #include "remoting/base/logging.h" | 26 #include "remoting/base/logging.h" |
26 #include "remoting/host/clipboard.h" | 27 #include "remoting/host/clipboard.h" |
27 #include "remoting/host/linux/unicode_to_keysym.h" | 28 #include "remoting/host/linux/unicode_to_keysym.h" |
| 29 #include "remoting/host/linux/x11_character_injector.h" |
| 30 #include "remoting/host/linux/x11_keyboard_impl.h" |
28 #include "remoting/host/linux/x11_util.h" | 31 #include "remoting/host/linux/x11_util.h" |
29 #include "remoting/proto/internal.pb.h" | 32 #include "remoting/proto/internal.pb.h" |
30 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" | 33 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" |
31 #include "ui/events/keycodes/dom/dom_code.h" | 34 #include "ui/events/keycodes/dom/dom_code.h" |
32 #include "ui/events/keycodes/dom/keycode_converter.h" | 35 #include "ui/events/keycodes/dom/keycode_converter.h" |
33 | 36 |
34 #if defined(OS_CHROMEOS) | 37 #if defined(OS_CHROMEOS) |
35 #include "remoting/host/chromeos/point_transformer.h" | 38 #include "remoting/host/chromeos/point_transformer.h" |
36 #endif | 39 #endif |
37 | 40 |
38 namespace remoting { | 41 namespace remoting { |
39 | 42 |
40 namespace { | 43 namespace { |
41 | 44 |
42 using protocol::ClipboardEvent; | 45 using protocol::ClipboardEvent; |
43 using protocol::KeyEvent; | 46 using protocol::KeyEvent; |
44 using protocol::TextEvent; | 47 using protocol::TextEvent; |
45 using protocol::MouseEvent; | 48 using protocol::MouseEvent; |
46 using protocol::TouchEvent; | 49 using protocol::TouchEvent; |
47 | 50 |
48 bool FindKeycodeForKeySym(Display* display, | |
49 KeySym key_sym, | |
50 uint32_t* keycode, | |
51 uint32_t* modifiers) { | |
52 *keycode = XKeysymToKeycode(display, key_sym); | |
53 | |
54 const uint32_t kModifiersToTry[] = { | |
55 0, | |
56 ShiftMask, | |
57 Mod2Mask, | |
58 Mod3Mask, | |
59 Mod4Mask, | |
60 ShiftMask | Mod2Mask, | |
61 ShiftMask | Mod3Mask, | |
62 ShiftMask | Mod4Mask, | |
63 }; | |
64 | |
65 // TODO(sergeyu): Is there a better way to find modifiers state? | |
66 for (size_t i = 0; i < arraysize(kModifiersToTry); ++i) { | |
67 unsigned long key_sym_with_mods; | |
68 if (XkbLookupKeySym(display, *keycode, kModifiersToTry[i], nullptr, | |
69 &key_sym_with_mods) && | |
70 key_sym_with_mods == key_sym) { | |
71 *modifiers = kModifiersToTry[i]; | |
72 return true; | |
73 } | |
74 } | |
75 | |
76 return false; | |
77 } | |
78 | |
79 // Finds a keycode and set of modifiers that generate character with the | |
80 // specified |code_point|. | |
81 bool FindKeycodeForUnicode(Display* display, | |
82 uint32_t code_point, | |
83 uint32_t* keycode, | |
84 uint32_t* modifiers) { | |
85 std::vector<uint32_t> keysyms; | |
86 GetKeySymsForUnicode(code_point, &keysyms); | |
87 | |
88 for (std::vector<uint32_t>::iterator it = keysyms.begin(); | |
89 it != keysyms.end(); ++it) { | |
90 if (FindKeycodeForKeySym(display, *it, keycode, modifiers)) { | |
91 return true; | |
92 } | |
93 } | |
94 | |
95 return false; | |
96 } | |
97 | |
98 bool IsModifierKey(ui::DomCode dom_code) { | 51 bool IsModifierKey(ui::DomCode dom_code) { |
99 return dom_code == ui::DomCode::CONTROL_LEFT || | 52 return dom_code == ui::DomCode::CONTROL_LEFT || |
100 dom_code == ui::DomCode::SHIFT_LEFT || | 53 dom_code == ui::DomCode::SHIFT_LEFT || |
101 dom_code == ui::DomCode::ALT_LEFT || | 54 dom_code == ui::DomCode::ALT_LEFT || |
102 dom_code == ui::DomCode::META_LEFT || | 55 dom_code == ui::DomCode::META_LEFT || |
103 dom_code == ui::DomCode::CONTROL_RIGHT || | 56 dom_code == ui::DomCode::CONTROL_RIGHT || |
104 dom_code == ui::DomCode::SHIFT_RIGHT || | 57 dom_code == ui::DomCode::SHIFT_RIGHT || |
105 dom_code == ui::DomCode::ALT_RIGHT || | 58 dom_code == ui::DomCode::ALT_RIGHT || |
106 dom_code == ui::DomCode::META_RIGHT; | 59 dom_code == ui::DomCode::META_RIGHT; |
107 } | 60 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 static const int kNumPointerButtons = 7; | 145 static const int kNumPointerButtons = 7; |
193 | 146 |
194 int pointer_button_map_[kNumPointerButtons]; | 147 int pointer_button_map_[kNumPointerButtons]; |
195 | 148 |
196 #if defined(OS_CHROMEOS) | 149 #if defined(OS_CHROMEOS) |
197 PointTransformer point_transformer_; | 150 PointTransformer point_transformer_; |
198 #endif | 151 #endif |
199 | 152 |
200 std::unique_ptr<Clipboard> clipboard_; | 153 std::unique_ptr<Clipboard> clipboard_; |
201 | 154 |
| 155 std::unique_ptr<X11CharacterInjector> character_injector_; |
| 156 |
202 bool saved_auto_repeat_enabled_; | 157 bool saved_auto_repeat_enabled_; |
203 | 158 |
204 DISALLOW_COPY_AND_ASSIGN(Core); | 159 DISALLOW_COPY_AND_ASSIGN(Core); |
205 }; | 160 }; |
206 | 161 |
207 scoped_refptr<Core> core_; | 162 scoped_refptr<Core> core_; |
208 | 163 |
209 DISALLOW_COPY_AND_ASSIGN(InputInjectorX11); | 164 DISALLOW_COPY_AND_ASSIGN(InputInjectorX11); |
210 }; | 165 }; |
211 | 166 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 } | 312 } |
358 pressed_keys_.clear(); | 313 pressed_keys_.clear(); |
359 | 314 |
360 const std::string text = event.text(); | 315 const std::string text = event.text(); |
361 for (int32_t index = 0; index < static_cast<int32_t>(text.size()); ++index) { | 316 for (int32_t index = 0; index < static_cast<int32_t>(text.size()); ++index) { |
362 uint32_t code_point; | 317 uint32_t code_point; |
363 if (!base::ReadUnicodeCharacter( | 318 if (!base::ReadUnicodeCharacter( |
364 text.c_str(), text.size(), &index, &code_point)) { | 319 text.c_str(), text.size(), &index, &code_point)) { |
365 continue; | 320 continue; |
366 } | 321 } |
367 | 322 character_injector_->Inject(code_point); |
368 uint32_t keycode; | |
369 uint32_t modifiers; | |
370 if (!FindKeycodeForUnicode(display_, code_point, &keycode, &modifiers)) | |
371 continue; | |
372 | |
373 XkbLockModifiers(display_, XkbUseCoreKbd, modifiers, modifiers); | |
374 | |
375 XTestFakeKeyEvent(display_, keycode, True, CurrentTime); | |
376 XTestFakeKeyEvent(display_, keycode, False, CurrentTime); | |
377 | |
378 XkbLockModifiers(display_, XkbUseCoreKbd, modifiers, 0); | |
379 } | 323 } |
380 | |
381 XFlush(display_); | |
382 } | 324 } |
383 | 325 |
384 InputInjectorX11::Core::~Core() { | 326 InputInjectorX11::Core::~Core() { |
385 CHECK(pressed_keys_.empty()); | 327 CHECK(pressed_keys_.empty()); |
386 } | 328 } |
387 | 329 |
388 void InputInjectorX11::Core::InitClipboard() { | 330 void InputInjectorX11::Core::InitClipboard() { |
389 DCHECK(task_runner_->BelongsToCurrentThread()); | 331 DCHECK(task_runner_->BelongsToCurrentThread()); |
390 clipboard_ = Clipboard::Create(); | 332 clipboard_ = Clipboard::Create(); |
391 } | 333 } |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 if (!task_runner_->BelongsToCurrentThread()) { | 569 if (!task_runner_->BelongsToCurrentThread()) { |
628 task_runner_->PostTask( | 570 task_runner_->PostTask( |
629 FROM_HERE, | 571 FROM_HERE, |
630 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); | 572 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); |
631 return; | 573 return; |
632 } | 574 } |
633 | 575 |
634 InitMouseButtonMap(); | 576 InitMouseButtonMap(); |
635 | 577 |
636 clipboard_->Start(std::move(client_clipboard)); | 578 clipboard_->Start(std::move(client_clipboard)); |
| 579 |
| 580 character_injector_.reset( |
| 581 new X11CharacterInjector(base::MakeUnique<X11KeyboardImpl>(display_))); |
637 } | 582 } |
638 | 583 |
639 void InputInjectorX11::Core::Stop() { | 584 void InputInjectorX11::Core::Stop() { |
640 if (!task_runner_->BelongsToCurrentThread()) { | 585 if (!task_runner_->BelongsToCurrentThread()) { |
641 task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); | 586 task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); |
642 return; | 587 return; |
643 } | 588 } |
644 | 589 |
645 clipboard_.reset(); | 590 clipboard_.reset(); |
| 591 character_injector_.reset(); |
646 } | 592 } |
647 | 593 |
648 } // namespace | 594 } // namespace |
649 | 595 |
650 // static | 596 // static |
651 std::unique_ptr<InputInjector> InputInjector::Create( | 597 std::unique_ptr<InputInjector> InputInjector::Create( |
652 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 598 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
653 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 599 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
654 std::unique_ptr<InputInjectorX11> injector( | 600 std::unique_ptr<InputInjectorX11> injector( |
655 new InputInjectorX11(main_task_runner)); | 601 new InputInjectorX11(main_task_runner)); |
656 if (!injector->Init()) | 602 if (!injector->Init()) |
657 return nullptr; | 603 return nullptr; |
658 return std::move(injector); | 604 return std::move(injector); |
659 } | 605 } |
660 | 606 |
661 // static | 607 // static |
662 bool InputInjector::SupportsTouchEvents() { | 608 bool InputInjector::SupportsTouchEvents() { |
663 return false; | 609 return false; |
664 } | 610 } |
665 | 611 |
666 } // namespace remoting | 612 } // namespace remoting |
OLD | NEW |