Chromium Code Reviews| 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/single_thread_task_runner.h" | 22 #include "base/single_thread_task_runner.h" |
| 23 #include "base/strings/utf_string_conversion_utils.h" | 23 #include "base/strings/utf_string_conversion_utils.h" |
| 24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
| 25 #include "remoting/base/logging.h" | 25 #include "remoting/base/logging.h" |
| 26 #include "remoting/host/clipboard.h" | 26 #include "remoting/host/clipboard.h" |
| 27 #include "remoting/host/linux/unicode_to_keysym.h" | 27 #include "remoting/host/linux/unicode_to_keysym.h" |
| 28 #include "remoting/host/linux/x11_util.h" | 28 #include "remoting/host/linux/x11_util.h" |
| 29 #include "remoting/host/linux/x_server_character_injector.h" | |
| 30 #include "remoting/host/linux/x_server_keyboard_interface.h" | |
| 29 #include "remoting/proto/internal.pb.h" | 31 #include "remoting/proto/internal.pb.h" |
| 30 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" | 32 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" |
| 31 #include "ui/events/keycodes/dom/dom_code.h" | 33 #include "ui/events/keycodes/dom/dom_code.h" |
| 32 #include "ui/events/keycodes/dom/keycode_converter.h" | 34 #include "ui/events/keycodes/dom/keycode_converter.h" |
| 33 | 35 |
| 34 #if defined(OS_CHROMEOS) | 36 #if defined(OS_CHROMEOS) |
| 35 #include "remoting/host/chromeos/point_transformer.h" | 37 #include "remoting/host/chromeos/point_transformer.h" |
| 36 #endif | 38 #endif |
| 37 | 39 |
| 38 namespace remoting { | 40 namespace remoting { |
| 39 | 41 |
| 40 namespace { | 42 namespace { |
| 41 | 43 |
| 42 using protocol::ClipboardEvent; | 44 using protocol::ClipboardEvent; |
| 43 using protocol::KeyEvent; | 45 using protocol::KeyEvent; |
| 44 using protocol::TextEvent; | 46 using protocol::TextEvent; |
| 45 using protocol::MouseEvent; | 47 using protocol::MouseEvent; |
| 46 using protocol::TouchEvent; | 48 using protocol::TouchEvent; |
| 47 | 49 |
| 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) { | 50 bool IsModifierKey(ui::DomCode dom_code) { |
| 99 return dom_code == ui::DomCode::CONTROL_LEFT || | 51 return dom_code == ui::DomCode::CONTROL_LEFT || |
| 100 dom_code == ui::DomCode::SHIFT_LEFT || | 52 dom_code == ui::DomCode::SHIFT_LEFT || |
| 101 dom_code == ui::DomCode::ALT_LEFT || | 53 dom_code == ui::DomCode::ALT_LEFT || |
| 102 dom_code == ui::DomCode::META_LEFT || | 54 dom_code == ui::DomCode::META_LEFT || |
| 103 dom_code == ui::DomCode::CONTROL_RIGHT || | 55 dom_code == ui::DomCode::CONTROL_RIGHT || |
| 104 dom_code == ui::DomCode::SHIFT_RIGHT || | 56 dom_code == ui::DomCode::SHIFT_RIGHT || |
| 105 dom_code == ui::DomCode::ALT_RIGHT || | 57 dom_code == ui::DomCode::ALT_RIGHT || |
| 106 dom_code == ui::DomCode::META_RIGHT; | 58 dom_code == ui::DomCode::META_RIGHT; |
| 107 } | 59 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 static const int kNumPointerButtons = 7; | 144 static const int kNumPointerButtons = 7; |
| 193 | 145 |
| 194 int pointer_button_map_[kNumPointerButtons]; | 146 int pointer_button_map_[kNumPointerButtons]; |
| 195 | 147 |
| 196 #if defined(OS_CHROMEOS) | 148 #if defined(OS_CHROMEOS) |
| 197 PointTransformer point_transformer_; | 149 PointTransformer point_transformer_; |
| 198 #endif | 150 #endif |
| 199 | 151 |
| 200 std::unique_ptr<Clipboard> clipboard_; | 152 std::unique_ptr<Clipboard> clipboard_; |
| 201 | 153 |
| 154 std::unique_ptr<XServerKeyboardInterface> keyboard_; | |
|
Sergey Ulanov
2016/09/21 19:59:23
Do you need this here? Can XServerCharacterInjecto
Yuwei
2016/09/23 01:40:37
Done.
| |
| 155 | |
| 156 std::unique_ptr<XServerCharacterInjector> character_injector_; | |
| 157 | |
| 202 bool saved_auto_repeat_enabled_; | 158 bool saved_auto_repeat_enabled_; |
| 203 | 159 |
| 204 DISALLOW_COPY_AND_ASSIGN(Core); | 160 DISALLOW_COPY_AND_ASSIGN(Core); |
| 205 }; | 161 }; |
| 206 | 162 |
| 207 scoped_refptr<Core> core_; | 163 scoped_refptr<Core> core_; |
| 208 | 164 |
| 209 DISALLOW_COPY_AND_ASSIGN(InputInjectorX11); | 165 DISALLOW_COPY_AND_ASSIGN(InputInjectorX11); |
| 210 }; | 166 }; |
| 211 | 167 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 } | 313 } |
| 358 pressed_keys_.clear(); | 314 pressed_keys_.clear(); |
| 359 | 315 |
| 360 const std::string text = event.text(); | 316 const std::string text = event.text(); |
| 361 for (int32_t index = 0; index < static_cast<int32_t>(text.size()); ++index) { | 317 for (int32_t index = 0; index < static_cast<int32_t>(text.size()); ++index) { |
| 362 uint32_t code_point; | 318 uint32_t code_point; |
| 363 if (!base::ReadUnicodeCharacter( | 319 if (!base::ReadUnicodeCharacter( |
| 364 text.c_str(), text.size(), &index, &code_point)) { | 320 text.c_str(), text.size(), &index, &code_point)) { |
| 365 continue; | 321 continue; |
| 366 } | 322 } |
| 367 | 323 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 } | 324 } |
| 380 | |
| 381 XFlush(display_); | |
| 382 } | 325 } |
| 383 | 326 |
| 384 InputInjectorX11::Core::~Core() { | 327 InputInjectorX11::Core::~Core() { |
| 385 CHECK(pressed_keys_.empty()); | 328 CHECK(pressed_keys_.empty()); |
| 386 } | 329 } |
| 387 | 330 |
| 388 void InputInjectorX11::Core::InitClipboard() { | 331 void InputInjectorX11::Core::InitClipboard() { |
| 389 DCHECK(task_runner_->BelongsToCurrentThread()); | 332 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 390 clipboard_ = Clipboard::Create(); | 333 clipboard_ = Clipboard::Create(); |
| 391 } | 334 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 if (!task_runner_->BelongsToCurrentThread()) { | 570 if (!task_runner_->BelongsToCurrentThread()) { |
| 628 task_runner_->PostTask( | 571 task_runner_->PostTask( |
| 629 FROM_HERE, | 572 FROM_HERE, |
| 630 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); | 573 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); |
| 631 return; | 574 return; |
| 632 } | 575 } |
| 633 | 576 |
| 634 InitMouseButtonMap(); | 577 InitMouseButtonMap(); |
| 635 | 578 |
| 636 clipboard_->Start(std::move(client_clipboard)); | 579 clipboard_->Start(std::move(client_clipboard)); |
| 580 | |
| 581 keyboard_.reset(new XServerKeyboardInterface(display_)); | |
| 582 character_injector_.reset(new XServerCharacterInjector(keyboard_.get())); | |
| 637 } | 583 } |
| 638 | 584 |
| 639 void InputInjectorX11::Core::Stop() { | 585 void InputInjectorX11::Core::Stop() { |
| 640 if (!task_runner_->BelongsToCurrentThread()) { | 586 if (!task_runner_->BelongsToCurrentThread()) { |
| 641 task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); | 587 task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); |
| 642 return; | 588 return; |
| 643 } | 589 } |
| 644 | 590 |
| 645 clipboard_.reset(); | 591 clipboard_.reset(); |
| 592 character_injector_.reset(); | |
| 593 keyboard_.reset(); | |
| 646 } | 594 } |
| 647 | 595 |
| 648 } // namespace | 596 } // namespace |
| 649 | 597 |
| 650 // static | 598 // static |
| 651 std::unique_ptr<InputInjector> InputInjector::Create( | 599 std::unique_ptr<InputInjector> InputInjector::Create( |
| 652 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 600 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 653 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 601 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
| 654 std::unique_ptr<InputInjectorX11> injector( | 602 std::unique_ptr<InputInjectorX11> injector( |
| 655 new InputInjectorX11(main_task_runner)); | 603 new InputInjectorX11(main_task_runner)); |
| 656 if (!injector->Init()) | 604 if (!injector->Init()) |
| 657 return nullptr; | 605 return nullptr; |
| 658 return std::move(injector); | 606 return std::move(injector); |
| 659 } | 607 } |
| 660 | 608 |
| 661 // static | 609 // static |
| 662 bool InputInjector::SupportsTouchEvents() { | 610 bool InputInjector::SupportsTouchEvents() { |
| 663 return false; | 611 return false; |
| 664 } | 612 } |
| 665 | 613 |
| 666 } // namespace remoting | 614 } // namespace remoting |
| OLD | NEW |