Commit 1a1adcb8 authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

[XProto] Remove all keyboard-related usage of Xlib

R=sky
BUG=1066670

Change-Id: Ibe851c24db25f4e7801e98918013914a297f063b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2436787
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812208}
parent 187cddbc
......@@ -102,15 +102,18 @@ int KeyboardCodeToXKeyCode(ui::KeyboardCode key_code) {
// Gets the X modifier mask (Mod1Mask through Mod5Mask) for the given
// modifier. Only checks the alt, meta, and num lock keys currently.
// Returns true on success.
bool GetXModifierMask(Display* display,
bool GetXModifierMask(x11::Connection* connection,
int modifier,
x11::KeyButMask* x_modifier) {
XModifierKeymap* mod_map = XGetModifierMapping(display);
auto mod_map = connection->GetModifierMapping({}).Sync();
if (!mod_map)
return false;
bool found = false;
int max_mod_keys = mod_map->max_keypermod;
int max_mod_keys = mod_map->keycodes_per_modifier;
for (int mod_index = 0; mod_index <= 8; ++mod_index) {
for (int key_index = 0; key_index < max_mod_keys; ++key_index) {
int key = mod_map->modifiermap[mod_index * max_mod_keys + key_index];
auto key = static_cast<uint8_t>(
mod_map->keycodes[mod_index * max_mod_keys + key_index]);
int keysym =
static_cast<int>(x11::Connection::Get()->KeycodeToKeysym(key, 0));
if (modifier == kAltKeyModifierMask)
......@@ -127,7 +130,6 @@ bool GetXModifierMask(Display* display,
if (found)
break;
}
XFreeModifiermap(mod_map);
return found;
}
......@@ -137,8 +139,8 @@ bool ConvertKeyCodeToText(ui::KeyboardCode key_code,
int modifiers,
std::string* text,
std::string* error_msg) {
XDisplay* display = gfx::GetXDisplay();
if (!display) {
auto* connection = x11::Connection::Get();
if (!connection || !connection->Ready()) {
return ConvertKeyCodeToTextOzone(key_code, modifiers, text, error_msg);
}
......@@ -160,15 +162,15 @@ bool ConvertKeyCodeToText(ui::KeyboardCode key_code,
// Make a best attempt for non-standard modifiers.
x11::KeyButMask x_modifier;
if (modifiers & kAltKeyModifierMask &&
GetXModifierMask(display, kAltKeyModifierMask, &x_modifier)) {
GetXModifierMask(connection, kAltKeyModifierMask, &x_modifier)) {
state = state | x_modifier;
}
if (modifiers & kMetaKeyModifierMask &&
GetXModifierMask(display, kMetaKeyModifierMask, &x_modifier)) {
GetXModifierMask(connection, kMetaKeyModifierMask, &x_modifier)) {
state = state | x_modifier;
}
if (modifiers & kNumLockKeyModifierMask &&
GetXModifierMask(display, kNumLockKeyModifierMask, &x_modifier)) {
GetXModifierMask(connection, kNumLockKeyModifierMask, &x_modifier)) {
state = state | x_modifier;
}
key_event.state = state;
......
......@@ -24,7 +24,10 @@ component("menu") {
"//ui/gfx",
]
if (use_x11) {
deps += [ "//ui/gfx/x" ]
deps += [
"//ui/events/keycodes:x11",
"//ui/gfx/x",
]
}
}
......
......@@ -6,11 +6,13 @@
#include <utility>
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
#include "ui/base/models/image_model.h"
#include "ui/base/models/menu_model.h"
#include "ui/events/keycodes/keysym_to_unicode.h"
#include "ui/gfx/image/image.h"
#if defined(USE_X11)
......@@ -48,17 +50,18 @@ MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu,
if (menu->GetAcceleratorAt(i, &accelerator)) {
std::vector<DbusString> parts;
if (accelerator.IsCtrlDown())
parts.push_back(DbusString("Control"));
parts.emplace_back("Control");
if (accelerator.IsAltDown())
parts.push_back(DbusString("Alt"));
parts.emplace_back("Alt");
if (accelerator.IsShiftDown())
parts.push_back(DbusString("Shift"));
parts.emplace_back("Shift");
if (accelerator.IsCmdDown())
parts.push_back(DbusString("Super"));
parts.emplace_back("Super");
#if defined(USE_X11)
if (!features::IsUsingOzonePlatform()) {
parts.push_back(DbusString(XKeysymToString(
XKeysymForWindowsKeyCode(accelerator.key_code(), false))));
uint16_t keysym = ui::GetUnicodeCharacterFromXKeySym(
XKeysymForWindowsKeyCode(accelerator.key_code(), false));
parts.emplace_back(base::UTF16ToUTF8(base::string16(1, keysym)));
properties["shortcut"] = MakeDbusVariant(
MakeDbusArray(DbusArray<DbusString>(std::move(parts))));
}
......
......@@ -57,8 +57,9 @@ enum class ScrollDirection {
};
ScrollDirection WheelDeltaToScrollDirection(float num) {
return (num > 0) ? ScrollDirection::UP
: (num < 0) ? ScrollDirection::DOWN : ScrollDirection::NONE;
return (num > 0) ? ScrollDirection::UP
: (num < 0) ? ScrollDirection::DOWN
: ScrollDirection::NONE;
}
bool IsDomModifierKey(ui::DomCode dom_code) {
......@@ -384,20 +385,19 @@ bool InputInjectorX11::Core::IsLockKey(KeyCode keycode) {
if (!state)
return false;
auto mods = state->baseMods | state->latchedMods | state->lockedMods;
KeySym keysym;
if (state && XkbLookupKeySym(display_, keycode, static_cast<unsigned>(mods),
nullptr, &keysym)) {
auto keysym = static_cast<uint32_t>(
connection_.KeycodeToKeysym(keycode, static_cast<unsigned>(mods)));
if (state && keysym)
return keysym == XK_Caps_Lock || keysym == XK_Num_Lock;
} else {
else
return false;
}
}
void InputInjectorX11::Core::SetLockStates(base::Optional<bool> caps_lock,
base::Optional<bool> num_lock) {
// The lock bits associated with each lock key.
unsigned int caps_lock_mask = XkbKeysymToModifiers(display_, XK_Caps_Lock);
unsigned int num_lock_mask = XkbKeysymToModifiers(display_, XK_Num_Lock);
auto caps_lock_mask = static_cast<unsigned int>(x11::ModMask::Lock);
auto num_lock_mask = static_cast<unsigned int>(x11::ModMask::c_2);
unsigned int update_mask = 0; // The lock bits we want to update
unsigned int lock_values = 0; // The value of those bits
......@@ -417,8 +417,10 @@ void InputInjectorX11::Core::SetLockStates(base::Optional<bool> caps_lock,
}
if (update_mask) {
XkbLockModifiers(display_, static_cast<unsigned>(x11::Xkb::Id::UseCoreKbd),
update_mask, lock_values);
connection_.xkb().LatchLockState(
{static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd),
static_cast<x11::ModMask>(update_mask),
static_cast<x11::ModMask>(lock_values)});
}
}
......
......@@ -15,11 +15,12 @@
namespace {
bool FindKeycodeForKeySym(Display* display,
KeySym key_sym,
bool FindKeycodeForKeySym(x11::Connection* connection,
x11::KeySym key_sym,
uint32_t* keycode,
uint32_t* modifiers) {
uint32_t found_keycode = XKeysymToKeycode(display, key_sym);
auto found_keycode =
static_cast<uint32_t>(connection->KeysymToKeycode(key_sym));
const x11::KeyButMask kModifiersToTry[] = {
{},
......@@ -34,11 +35,8 @@ bool FindKeycodeForKeySym(Display* display,
// TODO(sergeyu): Is there a better way to find modifiers state?
for (auto i : kModifiersToTry) {
int mods = static_cast<int>(i);
unsigned long key_sym_with_mods;
if (XkbLookupKeySym(display, found_keycode, mods, nullptr,
&key_sym_with_mods) &&
key_sym_with_mods == key_sym) {
auto mods = static_cast<uint32_t>(i);
if (connection->KeycodeToKeysym(found_keycode, mods) == key_sym) {
*modifiers = mods;
*keycode = found_keycode;
return true;
......@@ -58,46 +56,49 @@ X11KeyboardImpl::~X11KeyboardImpl() = default;
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;
uint8_t min_keycode = static_cast<uint8_t>(connection_->setup().min_keycode);
uint8_t max_keycode = static_cast<uint8_t>(connection_->setup().max_keycode);
uint8_t keycode_count = max_keycode - min_keycode + 1;
auto req = connection_->GetKeyboardMapping(
{connection_->setup().min_keycode, keycode_count});
if (auto reply = req.Sync()) {
for (int keycode = max_keycode; keycode >= min_keycode; keycode--) {
bool used = false;
int offset = (keycode - min_keycode) * reply->keysyms_per_keycode;
for (int level = 0; level < reply->keysyms_per_keycode; level++) {
if (reply->keysyms[offset + level] != x11::KeySym{}) {
used = true;
break;
}
}
}
if (!used) {
unused_keycodes_.push_back(keycode);
if (!used)
unused_keycodes_.push_back(keycode);
}
}
return unused_keycodes_;
}
void X11KeyboardImpl::PressKey(uint32_t keycode, uint32_t modifiers) {
XkbLockModifiers(display_, static_cast<unsigned>(x11::Xkb::Id::UseCoreKbd),
modifiers, modifiers);
connection_->xkb().LatchLockState(
{static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd),
static_cast<x11::ModMask>(modifiers),
static_cast<x11::ModMask>(modifiers)});
connection_->xtest().FakeInput({x11::KeyEvent::Press, keycode});
connection_->xtest().FakeInput({x11::KeyEvent::Release, keycode});
XkbLockModifiers(display_, static_cast<unsigned>(x11::Xkb::Id::UseCoreKbd),
modifiers, 0);
connection_->xkb().LatchLockState(
{static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd),
static_cast<x11::ModMask>(modifiers), x11::ModMask{}});
}
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)) {
if (FindKeycodeForKeySym(connection_, static_cast<x11::KeySym>(keysym),
keycode, modifiers)) {
return true;
}
}
......@@ -105,20 +106,22 @@ bool X11KeyboardImpl::FindKeycode(uint32_t code_point,
}
bool X11KeyboardImpl::ChangeKeyMapping(uint32_t keycode, uint32_t code_point) {
x11::KeySym sym{};
bool res = false;
if (code_point > 0) {
std::string sym_hex = base::StringPrintf("U%x", code_point);
sym = static_cast<x11::KeySym>(XStringToKeysym(sym_hex.c_str()));
if (sym == x11::KeySym{}) {
// The server may not support Unicode-to-KeySym translation.
return false;
for (auto keysym : GetKeySymsForUnicode(code_point)) {
if (keysym > 0xffff)
continue;
connection_->ChangeKeyboardMapping({
.keycode_count = 1,
.first_keycode = static_cast<x11::KeyCode>(keycode),
.keysyms_per_keycode = 2,
.keysyms = {static_cast<x11::KeySym>(keysym) /* lower-case */,
static_cast<x11::KeySym>(keysym) /* upper-case */},
});
res = true;
}
}
KeySym syms[2]{static_cast<KeySym>(sym) /* lower-case */,
static_cast<KeySym>(sym) /* upper-case */};
XChangeKeyboardMapping(display_, keycode, 2, syms, 1);
return true;
return res;
}
void X11KeyboardImpl::Flush() {
......
......@@ -7,13 +7,15 @@
#include <stdint.h>
#include "ui/events/keycodes/keycodes_x_export.h"
namespace ui {
// Returns a Unicode character corresponding to the given |keysym|. If the
// |keysym| doesn't represent a printable character, returns zero. We don't
// support characters outside the Basic Plane, and this function returns zero
// in that case.
uint16_t GetUnicodeCharacterFromXKeySym(unsigned long keysym);
KEYCODES_X_EXPORT uint16_t GetUnicodeCharacterFromXKeySym(unsigned long keysym);
} // namespace ui
......
......@@ -28,6 +28,10 @@ namespace ui {
namespace {
int XkbGroupForCoreState(int state) {
return (state >> 13) & 0x3;
}
// In X11 touch events, a new tracking_id/slot mapping is set up for each new
// event (see |ui::GetTouchIdFromXEvent| function), which needs to be cleared
// at destruction time for corresponding release/cancel events. In this
......
......@@ -47,11 +47,6 @@ using XErrorEvent = struct _XErrorEvent {
unsigned char minor_code;
};
using XModifierKeymap = struct {
int max_keypermod;
KeyCode* modifiermap;
};
using XErrorHandler = int (*)(Display*, XErrorEvent*);
using XIOErrorHandler = int (*)(Display*);
......@@ -72,26 +67,7 @@ int XGetErrorDatabaseText(Display*,
int XGetErrorText(Display*, int, char*, int);
XErrorHandler XSetErrorHandler(XErrorHandler);
XIOErrorHandler XSetIOErrorHandler(XIOErrorHandler);
KeyCode XKeysymToKeycode(Display*, KeySym);
char* XKeysymToString(KeySym);
XModifierKeymap* XGetModifierMapping(Display*);
int XFreeModifiermap(XModifierKeymap*);
int XStoreName(Display*, Window, const char*);
int XDisplayKeycodes(Display*, int*, int*);
KeySym* XGetKeyboardMapping(Display*, KeyCode, int, int*);
KeySym XStringToKeysym(const char*);
int XChangeKeyboardMapping(Display*, int, int, KeySym*, int);
Bool XkbLookupKeySym(Display*, KeyCode, unsigned int, unsigned int*, KeySym*);
Bool XkbLockModifiers(Display*, unsigned int, unsigned int, unsigned int);
unsigned int XkbKeysymToModifiers(Display*, KeySym);
}
inline int XkbGroupForCoreState(int s) {
return (s >> 13) & 0x3;
}
inline int XkbBuildCoreState(int m, int g) {
return ((g & 0x3) << 13) | (m & 0xff);
}
#endif // UI_GFX_X_X11_H_
......@@ -34,6 +34,14 @@
namespace ui {
namespace {
int XkbBuildCoreState(int key_button_mask, int group) {
return ((group & 0x3) << 13) | (key_button_mask & 0xff);
}
} // namespace
// Ensure DomKey extraction happens lazily in Ozone X11, while in non-Ozone
// path it is set right away in XEvent => ui::Event translation. This prevents
// regressions such as crbug.com/1007389.
......@@ -67,7 +75,7 @@ TEST(XEventTranslationTest, KeyEventXEventPropertiesSet) {
scoped_xev.InitKeyEvent(ET_KEY_PRESSED, VKEY_A, EF_NONE);
x11::Event* xev = scoped_xev;
XDisplay* xdisplay = gfx::GetXDisplay();
auto* connection = x11::Connection::Get();
// Set keyboard group in XKeyEvent
uint32_t state = XkbBuildCoreState(
static_cast<uint32_t>(xev->As<x11::KeyEvent>()->state), 2u);
......@@ -87,7 +95,9 @@ TEST(XEventTranslationTest, KeyEventXEventPropertiesSet) {
auto hw_keycode_it = properties->find(ui::kPropertyKeyboardHwKeyCode);
EXPECT_NE(hw_keycode_it, properties->end());
EXPECT_EQ(1u, hw_keycode_it->second.size());
EXPECT_EQ(XKeysymToKeycode(xdisplay, XK_a), hw_keycode_it->second[0]);
EXPECT_EQ(static_cast<uint8_t>(
connection->KeysymToKeycode(static_cast<x11::KeySym>(XK_a))),
hw_keycode_it->second[0]);
auto kbd_group_it = properties->find(ui::kPropertyKeyboardGroup);
EXPECT_NE(kbd_group_it, properties->end());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment