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

Side by Side Diff: remoting/host/linux/x11_character_injector.cc

Issue 2346643003: [Remoting Host] Handle text event characters that are not presented on the keyboard (Closed)
Patch Set: Reviewer's Feedback 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
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "remoting/host/linux/x11_character_injector.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "remoting/host/linux/x11_keyboard.h"
11
12 namespace {
13
14 constexpr base::TimeDelta kMappingExpireDuration =
15 base::TimeDelta::FromMilliseconds(200);
16
17 } // namespace
18
19 namespace remoting {
20
21 struct X11CharacterInjector::KeyInfo {
22 uint32_t keycode;
23 base::TimeTicks expire_at;
24 };
25
26 struct X11CharacterInjector::MapResult {
27 bool success;
28
29 uint32_t keycode;
30 uint32_t modifiers;
31
32 // If success == false and |retry_after| is not zero, user may retry
33 // AddNewCharacter() after |retry_after| has elapsed.
34 base::TimeDelta retry_after;
35 };
36
37 X11CharacterInjector::X11CharacterInjector(
38 std::unique_ptr<X11Keyboard> keyboard)
39 : keyboard_(std::move(keyboard)) {
40 std::vector<uint32_t> keycodes = keyboard_->GetUnusedKeycodes();
41 for (int keycode : keycodes) {
42 available_keycodes_.push_back({keycode, base::TimeTicks()});
43 }
44 }
45
46 X11CharacterInjector::~X11CharacterInjector() {
47 // Clear all used key mappings.
48 for (const KeyInfo& info : available_keycodes_) {
49 if (!info.expire_at.is_null()) {
50 keyboard_->ChangeKeyMapping(info.keycode, 0);
51 }
52 }
53 keyboard_->Sync();
54 }
55
56 void X11CharacterInjector::Inject(uint32_t code_point) {
57 DCHECK(thread_checker_.CalledOnValidThread());
58 characters_queue_.push(code_point);
59 Schedule(base::TimeDelta());
60 }
61
62 void X11CharacterInjector::Schedule(base::TimeDelta delay) {
63 DCHECK(thread_checker_.CalledOnValidThread());
64 if (injection_timer_.IsRunning()) {
65 return;
66 }
67 injection_timer_.Start(FROM_HERE, delay, this,
68 &X11CharacterInjector::DoInject);
69 }
70
71 void X11CharacterInjector::DoInject() {
72 DCHECK(thread_checker_.CalledOnValidThread());
73 while (!characters_queue_.empty()) {
74 uint32_t code_point = characters_queue_.front();
75 MapResult result = MapCharacter(code_point);
76 if (!result.success) {
77 if (result.retry_after.is_zero()) {
78 characters_queue_.pop();
79 continue;
80 }
81 Schedule(result.retry_after);
82 break;
83 }
84 keyboard_->PressKey(result.keycode, result.modifiers);
85 characters_queue_.pop();
86 }
87
88 keyboard_->Flush();
89 }
90
91 X11CharacterInjector::MapResult X11CharacterInjector::MapCharacter(
92 uint32_t code_point) {
93 MapResult result{false, 0, 0, base::TimeDelta()};
94
95 base::TimeTicks now = base::TimeTicks::Now();
96
97 if (keyboard_->FindKeycode(code_point, &result.keycode, &result.modifiers)) {
98 uint32_t keycode = result.keycode;
99 auto position = std::find_if(
100 available_keycodes_.begin(), available_keycodes_.end(),
101 [keycode](const KeyInfo& info) { return info.keycode == keycode; });
102 if (position != available_keycodes_.end()) {
103 ResetKeyInfoExpirationTime(now, position);
104 }
105 result.success = true;
106 return result;
107 }
108
109 if (available_keycodes_.empty()) {
110 return result;
111 }
112
113 KeyInfo& info = available_keycodes_.front();
114 if (info.expire_at > now) {
115 result.retry_after = info.expire_at - now;
116 return result;
117 }
118
119 if (!keyboard_->ChangeKeyMapping(info.keycode, code_point)) {
120 return result;
121 }
122
123 result.success = true;
124 result.keycode = info.keycode;
125
126 // Modifiers can always be 0 since |code_point| is mapped to both upper and
127 // lower case.
128
129 ResetKeyInfoExpirationTime(now, available_keycodes_.begin());
130
131 keyboard_->Sync();
132 return result;
133 }
134
135 void X11CharacterInjector::ResetKeyInfoExpirationTime(
136 base::TimeTicks now,
137 std::vector<KeyInfo>::iterator position) {
138 KeyInfo info = *position;
139 info.expire_at = now + kMappingExpireDuration;
140 available_keycodes_.erase(position);
141 available_keycodes_.push_back(info);
142 }
143
144 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/linux/x11_character_injector.h ('k') | remoting/host/linux/x11_character_injector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698