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

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

Powered by Google App Engine
This is Rietveld 408576698