Chromium Code Reviews| Index: remoting/host/linux/x_server_key_mapper.cc |
| diff --git a/remoting/host/linux/x_server_key_mapper.cc b/remoting/host/linux/x_server_key_mapper.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..01d0a961888541ba3d2f43316e8d090c7d258b3a |
| --- /dev/null |
| +++ b/remoting/host/linux/x_server_key_mapper.cc |
| @@ -0,0 +1,70 @@ |
| +// 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_key_mapper.h" |
| + |
| +#include <X11/Xlib.h> |
| + |
| +#include "base/strings/stringprintf.h" |
| +#include "ui/gfx/x/x11_types.h" |
| + |
| +namespace remoting { |
| + |
| +XServerKeyMapper::XServerKeyMapper(Display* display) : display_(display) { |
| + int min_keycode, max_keycode, sym_per_key; |
|
Sergey Ulanov
2016/09/19 21:39:00
nit: please move sym_per_key just before XGetKeybo
Yuwei
2016/09/21 03:47:40
Done.
|
| + XDisplayKeycodes(display_, &min_keycode, &max_keycode); |
| + uint32_t keycode_count = max_keycode - min_keycode + 1; |
| + 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) { |
| + available_keycodes_.push(keycode); |
| + } |
| + } |
| +} |
| + |
| +XServerKeyMapper::~XServerKeyMapper() { |
| + // Clear all used key mappings. |
| + KeySym empty = 0; |
| + for (int keycode : used_keycodes_) { |
| + XChangeKeyboardMapping(display_, keycode, 1, &empty, 1); |
| + } |
| + XSync(display_, false); |
| +} |
| + |
| +int XServerKeyMapper::AddNewCharacter(uint32_t code_point) { |
| + std::string sym_hex = base::StringPrintf("U%x", code_point); |
| + KeySym sym = XStringToKeysym(sym_hex.c_str()); |
| + if (sym == NoSymbol || available_keycodes_.empty()) { |
| + return -1; |
| + } |
| + |
| + // For alphabetic characters, both the upper-case and lower-case keysyms must |
| + // be defined as the character we want to type, otherwise Xlib will decide the |
| + // case by checking key modifiers. |
| + KeySym syms[2]; |
| + syms[0] = sym; // lower-case |
| + syms[1] = sym; // upper-case |
| + |
| + uint32_t keycode = available_keycodes_.front(); |
| + available_keycodes_.pop(); |
| + |
| + XChangeKeyboardMapping(display_, keycode, 2, syms, 1); |
| + |
| + available_keycodes_.push(keycode); |
| + used_keycodes_.insert(keycode); |
| + |
| + XSync(display_, false); |
| + return keycode; |
| +} |
| + |
| +} // namespace remoting |