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

Unified Diff: remoting/host/linux/x_server_keyboard_interface.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 side-by-side diff with in-line comments
Download patch
Index: remoting/host/linux/x_server_keyboard_interface.cc
diff --git a/remoting/host/linux/x_server_keyboard_interface.cc b/remoting/host/linux/x_server_keyboard_interface.cc
new file mode 100644
index 0000000000000000000000000000000000000000..94077973661c3107aafb2e65e350a0669e5e447a
--- /dev/null
+++ b/remoting/host/linux/x_server_keyboard_interface.cc
@@ -0,0 +1,142 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/linux/x_server_keyboard_interface.h"
+
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XTest.h>
+#include <X11/XKBlib.h>
+
+#include "base/strings/stringprintf.h"
+#include "remoting/host/linux/unicode_to_keysym.h"
+#include "ui/gfx/x/x11_types.h"
+
+namespace {
+
+bool FindKeycodeForKeySym(Display* display,
+ KeySym key_sym,
+ uint32_t* keycode,
+ uint32_t* modifiers) {
+ *keycode = XKeysymToKeycode(display, key_sym);
+
+ const uint32_t kModifiersToTry[] = {
+ 0,
+ ShiftMask,
+ Mod2Mask,
+ Mod3Mask,
+ Mod4Mask,
+ ShiftMask | Mod2Mask,
+ ShiftMask | Mod3Mask,
+ ShiftMask | Mod4Mask,
+ };
+
+ // TODO(sergeyu): Is there a better way to find modifiers state?
+ for (size_t i = 0; i < arraysize(kModifiersToTry); ++i) {
+ unsigned long key_sym_with_mods;
+ if (XkbLookupKeySym(display, *keycode, kModifiersToTry[i], nullptr,
+ &key_sym_with_mods) &&
+ key_sym_with_mods == key_sym) {
+ *modifiers = kModifiersToTry[i];
+ return true;
+ }
+ }
+ return false;
+}
+
+KeySym CodePointToKeySym(uint32_t code_point) {
+ if (code_point == 0) {
+ return NoSymbol;
+ }
+ std::string sym_hex = base::StringPrintf("U%x", code_point);
+ return XStringToKeysym(sym_hex.c_str());
+}
+
+} // namespace
+
+namespace remoting {
+
+XServerKeyboardInterface::XServerKeyboardInterface(Display* display) :
+ display_(display) {}
+
+XServerKeyboardInterface::~XServerKeyboardInterface() {}
+
+std::vector<uint32_t> XServerKeyboardInterface::GetUnusedKeycodes() {
+ std::vector<uint32_t> unused_keycodes_;
+ int min_keycode;
+ int max_keycode;
+ XDisplayKeycodes(display_, &min_keycode, &max_keycode);
+ uint32_t keycode_count = max_keycode - min_keycode + 1;
+
+ int sym_per_key;
+ gfx::XScopedPtr<KeySym> mapping(XGetKeyboardMapping(
+ display_, min_keycode, keycode_count, &sym_per_key));
+ for (int keycode = max_keycode; keycode >= min_keycode; keycode--) {
+ bool used = false;
+ int offset = (keycode - min_keycode) * sym_per_key;
+ for (int level = 0; level < sym_per_key; level++) {
+ if (mapping.get()[offset + level]) {
+ used = true;
+ break;
+ }
+ }
+ if (!used) {
+ unused_keycodes_.push_back(keycode);
+ }
+ }
+ return unused_keycodes_;
+}
+
+void XServerKeyboardInterface::PressKey(uint32_t keycode, uint32_t modifiers) {
+ XkbLockModifiers(display_, XkbUseCoreKbd, modifiers, modifiers);
+
+ XTestFakeKeyEvent(display_, keycode, True, CurrentTime);
+ XTestFakeKeyEvent(display_, keycode, False, CurrentTime);
+
+ XkbLockModifiers(display_, XkbUseCoreKbd, modifiers, 0);
+}
+
+bool XServerKeyboardInterface::FindKeycode(uint32_t code_point,
+ uint32_t* keycode,
+ uint32_t* modifiers) {
+ std::vector<uint32_t> keysyms;
+ GetKeySymsForUnicode(code_point, &keysyms);
+
+ for (std::vector<uint32_t>::iterator it = keysyms.begin();
Sergey Ulanov 2016/09/21 19:59:23 Use range loop please: for (auto& keysym : keysy
Yuwei 2016/09/23 01:40:38 Done.
+ it != keysyms.end(); ++it) {
+ if (FindKeycodeForKeySym(display_, *it, keycode, modifiers)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool XServerKeyboardInterface::ChangeKeyMapping(
+ uint32_t keycode,
Sergey Ulanov 2016/09/21 19:59:23 int instead of uint32_t.
Yuwei 2016/09/23 01:40:37 Is there any reason we prefer int? Looks like keyc
+ uint32_t lower_case_code_point,
+ uint32_t upper_case_code_point) {
Sergey Ulanov 2016/09/21 19:59:23 Maybe use KeySym for these two parameters?
Sergey Ulanov 2016/09/21 19:59:24 Do we need it here? It doesn't appear to be useful
Yuwei 2016/09/23 01:40:37 Removed. I just thought it could be useful if we
Yuwei 2016/09/23 01:40:37 KeySym is tyepdef'ed as unsigned int. I tried to a
+ KeySym lower_case_keysym = CodePointToKeySym(lower_case_code_point);
+ KeySym upper_case_keysum = (lower_case_code_point == upper_case_code_point) ?
+ lower_case_keysym : CodePointToKeySym(upper_case_code_point);
+ if ((lower_case_code_point && !lower_case_keysym) ||
+ (upper_case_code_point && !upper_case_keysum)) {
+ // Non-null code point translated to NoSymbol. The server may not support
+ // Unicode-to-KeySym translation.
+ return false;
+ }
+ KeySym syms[2];
Sergey Ulanov 2016/09/21 19:59:24 = {lower_case_keysym, upper_case_keysum};
Yuwei 2016/09/23 01:40:37 Done.
+ syms[0] = lower_case_keysym;
+ syms[1] = upper_case_keysum;
+ XChangeKeyboardMapping(display_, keycode, 2, syms, 1);
+ return true;
+}
+
+void XServerKeyboardInterface::Flush() {
+ XFlush(display_);
+}
+
+void XServerKeyboardInterface::Sync() {
+ XSync(display_, false);
+}
+
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698