| Index: remoting/host/linux/x11_keyboard_impl.cc
|
| diff --git a/remoting/host/linux/x11_keyboard_impl.cc b/remoting/host/linux/x11_keyboard_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0d47d1f3cd0abdb632afdb0914c10b20c18050ca
|
| --- /dev/null
|
| +++ b/remoting/host/linux/x11_keyboard_impl.cc
|
| @@ -0,0 +1,126 @@
|
| +// 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/x11_keyboard_impl.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) {
|
| + uint32_t found_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, found_keycode, kModifiersToTry[i], nullptr,
|
| + &key_sym_with_mods) &&
|
| + key_sym_with_mods == key_sym) {
|
| + *modifiers = kModifiersToTry[i];
|
| + *keycode = found_keycode;
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace remoting {
|
| +
|
| +X11KeyboardImpl::X11KeyboardImpl(Display* display) : display_(display) {}
|
| +
|
| +X11KeyboardImpl::~X11KeyboardImpl() {}
|
| +
|
| +std::vector<uint32_t> X11KeyboardImpl::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 X11KeyboardImpl::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 X11KeyboardImpl::FindKeycode(uint32_t code_point,
|
| + uint32_t* keycode,
|
| + uint32_t* modifiers) {
|
| + for (uint32_t keysym : GetKeySymsForUnicode(code_point)) {
|
| + if (FindKeycodeForKeySym(display_, keysym, keycode, modifiers)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool X11KeyboardImpl::ChangeKeyMapping(uint32_t keycode, uint32_t code_point) {
|
| + KeySym sym = NoSymbol;
|
| + if (code_point > 0) {
|
| + std::string sym_hex = base::StringPrintf("U%x", code_point);
|
| + sym = XStringToKeysym(sym_hex.c_str());
|
| + if (sym == NoSymbol) {
|
| + // The server may not support Unicode-to-KeySym translation.
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + KeySym syms[2]{sym, sym}; // {lower-case, upper-case}
|
| + XChangeKeyboardMapping(display_, keycode, 2, syms, 1);
|
| + return true;
|
| +}
|
| +
|
| +void X11KeyboardImpl::Flush() {
|
| + XFlush(display_);
|
| +}
|
| +
|
| +void X11KeyboardImpl::Sync() {
|
| + XSync(display_, false);
|
| +}
|
| +
|
| +} // namespace remoting
|
|
|