Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: remoting/host/input_injector_x11.cc

Issue 2346643003: [Remoting Host] Handle text event characters that are not presented on the keyboard (Closed)
Patch Set: Create KeyboardInterface and XServerKeyboardInterface Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698