Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/x_server_keyboard_interface.h" | |
| 6 | |
| 7 #include <X11/extensions/XInput.h> | |
| 8 #include <X11/extensions/XTest.h> | |
| 9 #include <X11/XKBlib.h> | |
| 10 | |
| 11 #include "base/strings/stringprintf.h" | |
| 12 #include "remoting/host/linux/unicode_to_keysym.h" | |
| 13 #include "ui/gfx/x/x11_types.h" | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 bool FindKeycodeForKeySym(Display* display, | |
| 18 KeySym key_sym, | |
| 19 uint32_t* keycode, | |
| 20 uint32_t* modifiers) { | |
| 21 *keycode = XKeysymToKeycode(display, key_sym); | |
| 22 | |
| 23 const uint32_t kModifiersToTry[] = { | |
| 24 0, | |
| 25 ShiftMask, | |
| 26 Mod2Mask, | |
| 27 Mod3Mask, | |
| 28 Mod4Mask, | |
| 29 ShiftMask | Mod2Mask, | |
| 30 ShiftMask | Mod3Mask, | |
| 31 ShiftMask | Mod4Mask, | |
| 32 }; | |
| 33 | |
| 34 // TODO(sergeyu): Is there a better way to find modifiers state? | |
| 35 for (size_t i = 0; i < arraysize(kModifiersToTry); ++i) { | |
| 36 unsigned long key_sym_with_mods; | |
| 37 if (XkbLookupKeySym(display, *keycode, kModifiersToTry[i], nullptr, | |
| 38 &key_sym_with_mods) && | |
| 39 key_sym_with_mods == key_sym) { | |
| 40 *modifiers = kModifiersToTry[i]; | |
| 41 return true; | |
| 42 } | |
| 43 } | |
| 44 return false; | |
| 45 } | |
| 46 | |
| 47 KeySym CodePointToKeySym(uint32_t code_point) { | |
| 48 if (code_point == 0) { | |
| 49 return NoSymbol; | |
| 50 } | |
| 51 std::string sym_hex = base::StringPrintf("U%x", code_point); | |
| 52 return XStringToKeysym(sym_hex.c_str()); | |
| 53 } | |
| 54 | |
| 55 } // namespace | |
| 56 | |
| 57 namespace remoting { | |
| 58 | |
| 59 XServerKeyboardInterface::XServerKeyboardInterface(Display* display) : | |
| 60 display_(display) {} | |
| 61 | |
| 62 XServerKeyboardInterface::~XServerKeyboardInterface() {} | |
| 63 | |
| 64 std::vector<uint32_t> XServerKeyboardInterface::GetUnusedKeycodes() { | |
| 65 std::vector<uint32_t> unused_keycodes_; | |
| 66 int min_keycode; | |
| 67 int max_keycode; | |
| 68 XDisplayKeycodes(display_, &min_keycode, &max_keycode); | |
| 69 uint32_t keycode_count = max_keycode - min_keycode + 1; | |
| 70 | |
| 71 int sym_per_key; | |
| 72 gfx::XScopedPtr<KeySym> mapping(XGetKeyboardMapping( | |
| 73 display_, min_keycode, keycode_count, &sym_per_key)); | |
| 74 for (int keycode = max_keycode; keycode >= min_keycode; keycode--) { | |
| 75 bool used = false; | |
| 76 int offset = (keycode - min_keycode) * sym_per_key; | |
| 77 for (int level = 0; level < sym_per_key; level++) { | |
| 78 if (mapping.get()[offset + level]) { | |
| 79 used = true; | |
| 80 break; | |
| 81 } | |
| 82 } | |
| 83 if (!used) { | |
| 84 unused_keycodes_.push_back(keycode); | |
| 85 } | |
| 86 } | |
| 87 return unused_keycodes_; | |
| 88 } | |
| 89 | |
| 90 void XServerKeyboardInterface::PressKey(uint32_t keycode, uint32_t modifiers) { | |
| 91 XkbLockModifiers(display_, XkbUseCoreKbd, modifiers, modifiers); | |
| 92 | |
| 93 XTestFakeKeyEvent(display_, keycode, True, CurrentTime); | |
| 94 XTestFakeKeyEvent(display_, keycode, False, CurrentTime); | |
| 95 | |
| 96 XkbLockModifiers(display_, XkbUseCoreKbd, modifiers, 0); | |
| 97 } | |
| 98 | |
| 99 bool XServerKeyboardInterface::FindKeycode(uint32_t code_point, | |
| 100 uint32_t* keycode, | |
| 101 uint32_t* modifiers) { | |
| 102 std::vector<uint32_t> keysyms; | |
| 103 GetKeySymsForUnicode(code_point, &keysyms); | |
| 104 | |
| 105 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.
| |
| 106 it != keysyms.end(); ++it) { | |
| 107 if (FindKeycodeForKeySym(display_, *it, keycode, modifiers)) { | |
| 108 return true; | |
| 109 } | |
| 110 } | |
| 111 return false; | |
| 112 } | |
| 113 | |
| 114 bool XServerKeyboardInterface::ChangeKeyMapping( | |
| 115 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
| |
| 116 uint32_t lower_case_code_point, | |
| 117 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
| |
| 118 KeySym lower_case_keysym = CodePointToKeySym(lower_case_code_point); | |
| 119 KeySym upper_case_keysum = (lower_case_code_point == upper_case_code_point) ? | |
| 120 lower_case_keysym : CodePointToKeySym(upper_case_code_point); | |
| 121 if ((lower_case_code_point && !lower_case_keysym) || | |
| 122 (upper_case_code_point && !upper_case_keysum)) { | |
| 123 // Non-null code point translated to NoSymbol. The server may not support | |
| 124 // Unicode-to-KeySym translation. | |
| 125 return false; | |
| 126 } | |
| 127 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.
| |
| 128 syms[0] = lower_case_keysym; | |
| 129 syms[1] = upper_case_keysum; | |
| 130 XChangeKeyboardMapping(display_, keycode, 2, syms, 1); | |
| 131 return true; | |
| 132 } | |
| 133 | |
| 134 void XServerKeyboardInterface::Flush() { | |
| 135 XFlush(display_); | |
| 136 } | |
| 137 | |
| 138 void XServerKeyboardInterface::Sync() { | |
| 139 XSync(display_, false); | |
| 140 } | |
| 141 | |
| 142 } // namespace remoting | |
| OLD | NEW |