summaryrefslogtreecommitdiff
path: root/chromium/ui/gfx/x
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/gfx/x')
-rw-r--r--chromium/ui/gfx/x/BUILD.gn53
-rw-r--r--chromium/ui/gfx/x/DEPS3
-rw-r--r--chromium/ui/gfx/x/OWNERS2
-rw-r--r--chromium/ui/gfx/x/connection.cc545
-rw-r--r--chromium/ui/gfx/x/connection.h76
-rw-r--r--chromium/ui/gfx/x/connection_unittest.cc16
-rw-r--r--chromium/ui/gfx/x/error.cc13
-rw-r--r--chromium/ui/gfx/x/error.h26
-rw-r--r--chromium/ui/gfx/x/event.cc13
-rw-r--r--chromium/ui/gfx/x/event.h6
-rw-r--r--chromium/ui/gfx/x/gen_xproto.py134
-rw-r--r--chromium/ui/gfx/x/keyboard_state.cc136
-rw-r--r--chromium/ui/gfx/x/keyboard_state.h37
-rw-r--r--chromium/ui/gfx/x/keysyms/keysyms.h1151
-rw-r--r--chromium/ui/gfx/x/scoped_ignore_errors.cc25
-rw-r--r--chromium/ui/gfx/x/scoped_ignore_errors.h26
-rw-r--r--chromium/ui/gfx/x/x11.h73
-rw-r--r--chromium/ui/gfx/x/x11_atom_cache.cc9
-rw-r--r--chromium/ui/gfx/x/x11_atom_cache.h2
-rw-r--r--chromium/ui/gfx/x/x11_error_tracker.cc41
-rw-r--r--chromium/ui/gfx/x/x11_error_tracker.h37
-rw-r--r--chromium/ui/gfx/x/x11_path.cc1
-rw-r--r--chromium/ui/gfx/x/x11_types.cc22
-rw-r--r--chromium/ui/gfx/x/x11_types.h45
-rw-r--r--chromium/ui/gfx/x/xlib.h17
-rw-r--r--chromium/ui/gfx/x/xlib_support.cc101
-rw-r--r--chromium/ui/gfx/x/xlib_support.h73
-rw-r--r--chromium/ui/gfx/x/xproto_internal.cc1
-rw-r--r--chromium/ui/gfx/x/xproto_internal.h9
-rw-r--r--chromium/ui/gfx/x/xproto_types.cc68
-rw-r--r--chromium/ui/gfx/x/xproto_types.h86
-rw-r--r--chromium/ui/gfx/x/xproto_util.cc62
-rw-r--r--chromium/ui/gfx/x/xproto_util.h6
33 files changed, 958 insertions, 1957 deletions
diff --git a/chromium/ui/gfx/x/BUILD.gn b/chromium/ui/gfx/x/BUILD.gn
index 6b87f8e0c12..96f72a4369a 100644
--- a/chromium/ui/gfx/x/BUILD.gn
+++ b/chromium/ui/gfx/x/BUILD.gn
@@ -2,8 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/ozone.gni")
import("//build/config/ui.gni")
-import("//ui/ozone/ozone.gni")
+import("//tools/generate_library_loader/generate_library_loader.gni")
assert(use_x11 || ozone_platform_x11)
@@ -20,6 +21,22 @@ config("x11_private_config") {
defines = [ "IS_X11_IMPL" ]
}
+generate_library_loader("xlib_loader") {
+ name = "XlibLoader"
+ output_h = "xlib_loader.h"
+ output_cc = "xlib_loader.cc"
+ header = "\"ui/gfx/x/xlib.h\""
+
+ functions = [
+ "XInitThreads",
+ "XOpenDisplay",
+ "XCloseDisplay",
+ "XFlush",
+ "XSynchronize",
+ "XSetErrorHandler",
+ ]
+}
+
action("gen_xprotos") {
visibility = [ ":xprotos" ]
script = "gen_xproto.py"
@@ -59,6 +76,7 @@ action("gen_xprotos") {
sources = []
outputs = [
"$target_gen_dir/read_event.cc",
+ "$target_gen_dir/read_error.cc",
"$target_gen_dir/extension_manager.h",
"$target_gen_dir/extension_manager.cc",
]
@@ -80,30 +98,35 @@ action("gen_xprotos") {
component("xprotos") {
deps = [
":gen_xprotos",
+ ":xlib_loader",
"//base",
"//base:i18n",
"//ui/events/platform",
]
public_deps = [ "//ui/gfx/x/keysyms" ]
sources = get_target_outputs(":gen_xprotos") + [
- "xproto_internal.h",
- "xproto_internal.cc",
- "xproto_types.h",
- "xproto_types.cc",
- "xproto_util.h",
- "xproto_util.cc",
"connection.h",
"connection.cc",
"event.h",
"event.cc",
+ "error.h",
+ "error.cc",
+ "keyboard_state.h",
+ "keyboard_state.cc",
+ "scoped_ignore_errors.h",
+ "scoped_ignore_errors.cc",
"x11_switches.cc",
"x11_switches.h",
- "x11.h",
+ "xlib_support.h",
+ "xlib_support.cc",
+ "xproto_internal.h",
+ "xproto_internal.cc",
+ "xproto_types.h",
+ "xproto_types.cc",
+ "xproto_util.h",
]
- configs += [
- ":x11_private_config",
- "//build/config/linux:x11",
- ]
+ configs += [ ":x11_private_config" ]
+ libs = [ "xcb" ]
}
component("x") {
@@ -113,18 +136,12 @@ component("x") {
"../gfx_export.h",
"x11_atom_cache.cc",
"x11_atom_cache.h",
- "x11_error_tracker.cc",
- "x11_error_tracker.h",
"x11_path.cc",
"x11_path.h",
- "x11_types.cc",
- "x11_types.h",
]
defines = [ "GFX_IMPLEMENTATION" ]
- public_configs = [ "//build/config/linux:x11" ]
-
deps = [
"//base",
"//skia",
diff --git a/chromium/ui/gfx/x/DEPS b/chromium/ui/gfx/x/DEPS
index a444e969cbd..eccf1f06866 100644
--- a/chromium/ui/gfx/x/DEPS
+++ b/chromium/ui/gfx/x/DEPS
@@ -1,3 +1,6 @@
include_rules = [
"+ui/events/platform/platform_event_source.h",
+ "+third_party/libx11",
+ "+third_party/libxcb-keysyms",
+ "+third_party/x11proto",
]
diff --git a/chromium/ui/gfx/x/OWNERS b/chromium/ui/gfx/x/OWNERS
index 079174d24bc..c5442ff2356 100644
--- a/chromium/ui/gfx/x/OWNERS
+++ b/chromium/ui/gfx/x/OWNERS
@@ -2,5 +2,3 @@ thomasanderson@chromium.org
# Adding new atoms is allowed without OWNERS review.
per-file x11_atom_cache.cc=*
-
-# COMPONENT: UI>GFX
diff --git a/chromium/ui/gfx/x/connection.cc b/chromium/ui/gfx/x/connection.cc
index cea4895e776..d6350747a89 100644
--- a/chromium/ui/gfx/x/connection.cc
+++ b/chromium/ui/gfx/x/connection.cc
@@ -11,55 +11,25 @@
#include "base/auto_reset.h"
#include "base/command_line.h"
-#include "base/i18n/case_conversion.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/strings/string16.h"
#include "base/threading/thread_local.h"
#include "ui/gfx/x/bigreq.h"
#include "ui/gfx/x/event.h"
-#include "ui/gfx/x/keysyms/keysyms.h"
+#include "ui/gfx/x/keyboard_state.h"
#include "ui/gfx/x/randr.h"
-#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_switches.h"
#include "ui/gfx/x/xkb.h"
#include "ui/gfx/x/xproto.h"
#include "ui/gfx/x/xproto_internal.h"
#include "ui/gfx/x/xproto_types.h"
-extern "C" {
-typedef struct {
- int type;
- unsigned long serial;
- Bool send_event;
- Display* display;
- Window window;
- Window root;
- Window subwindow;
- Time time;
- int x, y;
- int x_root, y_root;
- unsigned int state;
- unsigned int keycode;
- Bool same_screen;
-} XKeyEvent;
-
-// This is temporarily required to fix XKB key event processing (bugs 1125886,
-// 1136265, 1136248, 1136206). It should be removed and replaced with an
-// XProto equivalent.
-int XLookupString(XKeyEvent* event_struct,
- char* buffer_return,
- int bytes_buffer,
- ::KeySym* keysym_return,
- void* status_in_out);
-}
-
namespace x11 {
namespace {
-constexpr KeySym kNoSymbol = static_cast<KeySym>(0);
-
// On the wire, sequence IDs are 16 bits. In xcb, they're usually extended to
// 32 and sometimes 64 bits. In Xlib, they're extended to unsigned long, which
// may be 32 or 64 bits depending on the platform. This function is intended to
@@ -81,161 +51,45 @@ auto CompareSequenceIds(T t, U u) {
return static_cast<SignedType>(t0 - u0);
}
-XDisplay* OpenNewXDisplay(const std::string& address) {
- if (!XInitThreads())
- return nullptr;
- std::string display_str =
- address.empty()
- ? base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kX11Display)
- : address;
- return XOpenDisplay(display_str.empty() ? nullptr : display_str.c_str());
-}
-
-// Ported from XConvertCase:
-// https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/2b7598221d87049d03e9a95fcb541c37c8728184/src/KeyBind.c#L645
-void ConvertCaseImpl(uint32_t sym, uint32_t* lower, uint32_t* upper) {
- // Unicode keysym
- if ((sym & 0xff000000) == 0x01000000) {
- base::string16 string({sym & 0x00ffffff});
- auto lower_string = base::i18n::ToLower(string);
- auto upper_string = base::i18n::ToUpper(string);
- *lower = lower_string[0] | 0x01000000;
- *upper = upper_string[0] | 0x01000000;
- return;
- }
-
- *lower = sym;
- *upper = sym;
-
- switch (sym >> 8) {
- // Latin 1
- case 0:
- if ((sym >= XK_A) && (sym <= XK_Z))
- *lower += (XK_a - XK_A);
- else if ((sym >= XK_a) && (sym <= XK_z))
- *upper -= (XK_a - XK_A);
- else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
- *lower += (XK_agrave - XK_Agrave);
- else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
- *upper -= (XK_agrave - XK_Agrave);
- else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
- *lower += (XK_oslash - XK_Ooblique);
- else if ((sym >= XK_oslash) && (sym <= XK_thorn))
- *upper -= (XK_oslash - XK_Ooblique);
- break;
- // Latin 2
- case 1:
- if (sym == XK_Aogonek)
- *lower = XK_aogonek;
- else if (sym >= XK_Lstroke && sym <= XK_Sacute)
- *lower += (XK_lstroke - XK_Lstroke);
- else if (sym >= XK_Scaron && sym <= XK_Zacute)
- *lower += (XK_scaron - XK_Scaron);
- else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
- *lower += (XK_zcaron - XK_Zcaron);
- else if (sym == XK_aogonek)
- *upper = XK_Aogonek;
- else if (sym >= XK_lstroke && sym <= XK_sacute)
- *upper -= (XK_lstroke - XK_Lstroke);
- else if (sym >= XK_scaron && sym <= XK_zacute)
- *upper -= (XK_scaron - XK_Scaron);
- else if (sym >= XK_zcaron && sym <= XK_zabovedot)
- *upper -= (XK_zcaron - XK_Zcaron);
- else if (sym >= XK_Racute && sym <= XK_Tcedilla)
- *lower += (XK_racute - XK_Racute);
- else if (sym >= XK_racute && sym <= XK_tcedilla)
- *upper -= (XK_racute - XK_Racute);
- break;
- // Latin 3
- case 2:
- if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
- *lower += (XK_hstroke - XK_Hstroke);
- else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
- *lower += (XK_gbreve - XK_Gbreve);
- else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
- *upper -= (XK_hstroke - XK_Hstroke);
- else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
- *upper -= (XK_gbreve - XK_Gbreve);
- else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
- *lower += (XK_cabovedot - XK_Cabovedot);
- else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
- *upper -= (XK_cabovedot - XK_Cabovedot);
- break;
- // Latin 4
- case 3:
- if (sym >= XK_Rcedilla && sym <= XK_Tslash)
- *lower += (XK_rcedilla - XK_Rcedilla);
- else if (sym >= XK_rcedilla && sym <= XK_tslash)
- *upper -= (XK_rcedilla - XK_Rcedilla);
- else if (sym == XK_ENG)
- *lower = XK_eng;
- else if (sym == XK_eng)
- *upper = XK_ENG;
- else if (sym >= XK_Amacron && sym <= XK_Umacron)
- *lower += (XK_amacron - XK_Amacron);
- else if (sym >= XK_amacron && sym <= XK_umacron)
- *upper -= (XK_amacron - XK_Amacron);
- break;
- // Cyrillic
- case 6:
- if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
- *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
- else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
- *upper += (XK_Serbian_DJE - XK_Serbian_dje);
- else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
- *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
- else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
- *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
- break;
- // Greek
- case 7:
- if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
- *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
- else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
- sym != XK_Greek_iotaaccentdieresis &&
- sym != XK_Greek_upsilonaccentdieresis)
- *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
- else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
- *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
- else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
- sym != XK_Greek_finalsmallsigma)
- *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
- break;
- // Latin 9
- case 0x13:
- if (sym == XK_OE)
- *lower = XK_oe;
- else if (sym == XK_oe)
- *upper = XK_OE;
- else if (sym == XK_Ydiaeresis)
- *lower = XK_ydiaeresis;
- break;
- }
+base::ThreadLocalOwnedPointer<Connection>& GetConnectionTLS() {
+ static base::NoDestructor<base::ThreadLocalOwnedPointer<Connection>> tls;
+ return *tls;
}
-void ConvertCase(KeySym sym, KeySym* lower, KeySym* upper) {
- uint32_t lower32;
- uint32_t upper32;
- ConvertCaseImpl(static_cast<uint32_t>(sym), &lower32, &upper32);
- *lower = static_cast<KeySym>(lower32);
- *upper = static_cast<KeySym>(upper32);
+void DefaultErrorHandler(const x11::Error* error, const char* request_name) {
+ LOG(WARNING) << "X error received. Request: x11::" << request_name
+ << "Request, Error: " << error->ToString();
}
-bool IsXKeypadKey(KeySym keysym) {
- auto key = static_cast<uint32_t>(keysym);
- return key >= XK_KP_Space && key <= XK_KP_Equal;
+void DefaultIOErrorHandler() {
+ LOG(ERROR) << "X connection error received.";
}
-bool IsPrivateXKeypadKey(KeySym keysym) {
- auto key = static_cast<uint32_t>(keysym);
- return key >= 0x11000000 && key <= 0x1100FFFF;
-}
+class UnknownError : public Error {
+ public:
+ explicit UnknownError(FutureBase::RawError error_bytes)
+ : error_bytes_(error_bytes) {}
-base::ThreadLocalOwnedPointer<Connection>& GetConnectionTLS() {
- static base::NoDestructor<base::ThreadLocalOwnedPointer<Connection>> tls;
- return *tls;
-}
+ ~UnknownError() override = default;
+
+ std::string ToString() const override {
+ std::stringstream ss;
+ ss << "x11::UnknownError{";
+ // Errors are always a fixed 32 bytes.
+ for (size_t i = 0; i < 32; i++) {
+ char buf[3];
+ sprintf(buf, "%02x", error_bytes_->data()[i]);
+ ss << "0x" << buf;
+ if (i != 31)
+ ss << ", ";
+ }
+ ss << "}";
+ return ss.str();
+ }
+
+ private:
+ FutureBase::RawError error_bytes_;
+};
} // namespace
@@ -260,16 +114,18 @@ void Connection::Set(std::unique_ptr<x11::Connection> connection) {
Connection::Connection(const std::string& address)
: XProto(this),
- display_(OpenNewXDisplay(address)),
- display_string_(address) {
- char* host = nullptr;
- int display = 0;
- xcb_parse_display(address.c_str(), &host, &display, &default_screen_id_);
- if (host)
- free(host);
- if (display_) {
- XSetEventQueueOwner(display_, XCBOwnsEventQueue);
-
+ display_string_(
+ address.empty()
+ ? base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kX11Display)
+ : address),
+ error_handler_(base::BindRepeating(DefaultErrorHandler)),
+ io_error_handler_(base::BindOnce(DefaultIOErrorHandler)) {
+ connection_ =
+ xcb_connect(display_string_.empty() ? nullptr : display_string_.c_str(),
+ &default_screen_id_);
+ DCHECK(connection_);
+ if (Ready()) {
auto buf = ReadBuffer(base::MakeRefCounted<UnretainedRefCountedMemory>(
xcb_get_setup(XcbConnection())));
setup_ = Read<Setup>(&buf);
@@ -286,7 +142,17 @@ Connection::Connection(const std::string& address)
}
ExtensionManager::Init(this);
- if (auto response = bigreq().Enable({}).Sync())
+ auto enable_bigreq = bigreq().Enable({});
+ // Xlib enables XKB on display creation, so we do that here to maintain
+ // compatibility.
+ xkb()
+ .UseExtension({x11::Xkb::major_version, x11::Xkb::minor_version})
+ .OnResponse(base::BindOnce([](x11::Xkb::UseExtensionResponse response) {
+ if (!response || !response->supported)
+ DVLOG(1) << "Xkb extension not available.";
+ }));
+ Flush();
+ if (auto response = enable_bigreq.Sync())
extended_max_request_length_ = response->maximum_request_length;
const Format* formats[256];
@@ -300,21 +166,30 @@ Connection::Connection(const std::string& address)
default_screen_visuals_[visual.visual_id] = VisualInfo{format, &visual};
}
- ResetKeyboardState();
+ keyboard_state_ = CreateKeyboardState(this);
+
+ InitErrorParsers();
}
Connection::~Connection() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
platform_event_source.reset();
- if (display_)
- XCloseDisplay(display_);
+ xcb_disconnect(connection_);
}
xcb_connection_t* Connection::XcbConnection() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!display())
- return nullptr;
- return XGetXCBConnection(display());
+ if (io_error_handler_ && xcb_connection_has_error(connection_))
+ std::move(io_error_handler_).Run();
+ return connection_;
+}
+
+XlibDisplayWrapper Connection::GetXlibDisplay(XlibDisplayType type) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!xlib_display_)
+ xlib_display_ = base::WrapUnique(new XlibDisplay(display_string_));
+ return XlibDisplayWrapper(xlib_display_->display_, type);
}
Connection::Request::Request(unsigned int sequence,
@@ -322,14 +197,39 @@ Connection::Request::Request(unsigned int sequence,
: sequence(sequence), callback(std::move(callback)) {}
Connection::Request::Request(Request&& other)
- : sequence(other.sequence), callback(std::move(other.callback)) {}
+ : sequence(other.sequence),
+ callback(std::move(other.callback)),
+ have_response(other.have_response),
+ reply(std::move(other.reply)),
+ error(std::move(other.error)) {}
Connection::Request::~Request() = default;
-bool Connection::HasNextResponse() const {
- return !requests_.empty() &&
- CompareSequenceIds(XLastKnownRequestProcessed(display_),
- requests_.front().sequence) >= 0;
+bool Connection::HasNextResponse() {
+ if (requests_.empty())
+ return false;
+ auto& request = requests_.front();
+ if (request.have_response)
+ return true;
+
+ void* reply = nullptr;
+ xcb_generic_error_t* error = nullptr;
+ request.have_response =
+ xcb_poll_for_reply(XcbConnection(), request.sequence, &reply, &error);
+ if (reply)
+ request.reply = base::MakeRefCounted<MallocedRefCountedMemory>(reply);
+ if (error)
+ request.error = base::MakeRefCounted<MallocedRefCountedMemory>(error);
+ return request.have_response;
+}
+
+bool Connection::HasNextEvent() {
+ while (!events_.empty()) {
+ if (events_.front().Initialized())
+ return true;
+ events_.pop_front();
+ }
+ return false;
}
int Connection::GetFd() {
@@ -342,6 +242,19 @@ const std::string& Connection::DisplayString() const {
return display_string_;
}
+std::string Connection::GetConnectionHostname() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ char* host = nullptr;
+ int display_id = 0;
+ int screen = 0;
+ if (xcb_parse_display(display_string_.c_str(), &host, &display_id, &screen)) {
+ std::string name = host;
+ free(host);
+ return name;
+ }
+ return std::string();
+}
+
int Connection::DefaultScreenId() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// This is not part of the setup data as the server has no concept of a
@@ -352,13 +265,12 @@ int Connection::DefaultScreenId() const {
bool Connection::Ready() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return display_ && !xcb_connection_has_error(XGetXCBConnection(display_));
+ return !xcb_connection_has_error(connection_);
}
void Connection::Flush() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (display_)
- XFlush(display_);
+ xcb_flush(connection_);
}
void Connection::Sync() {
@@ -373,7 +285,6 @@ void Connection::Sync() {
void Connection::SynchronizeForTest(bool synchronous) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- XSynchronize(display(), synchronous);
synchronous_ = synchronous;
if (synchronous_)
Sync();
@@ -389,7 +300,7 @@ void Connection::ReadResponses() {
Event Connection::WaitForNextEvent() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!events_.empty()) {
+ if (HasNextEvent()) {
Event event = std::move(events_.front());
events_.pop_front();
return event;
@@ -401,9 +312,9 @@ Event Connection::WaitForNextEvent() {
return Event();
}
-bool Connection::HasPendingResponses() const {
+bool Connection::HasPendingResponses() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return !events_.empty() || HasNextResponse();
+ return HasNextEvent() || HasNextResponse();
}
const Connection::VisualInfo* Connection::GetVisualInfoFromId(
@@ -415,34 +326,15 @@ const Connection::VisualInfo* Connection::GetVisualInfoFromId(
return nullptr;
}
-KeyCode Connection::KeysymToKeycode(KeySym keysym) {
+KeyCode Connection::KeysymToKeycode(uint32_t keysym) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- uint8_t min_keycode = static_cast<uint8_t>(setup_.min_keycode);
- uint8_t max_keycode = static_cast<uint8_t>(setup_.max_keycode);
- uint8_t count = max_keycode - min_keycode + 1;
- DCHECK_EQ(count * keyboard_mapping_.keysyms_per_keycode,
- static_cast<int>(keyboard_mapping_.keysyms.size()));
- for (size_t i = 0; i < keyboard_mapping_.keysyms.size(); i++) {
- if (keyboard_mapping_.keysyms[i] == keysym) {
- return static_cast<KeyCode>(min_keycode +
- i / keyboard_mapping_.keysyms_per_keycode);
- }
- }
- return {};
+ return keyboard_state_->KeysymToKeycode(keysym);
}
-KeySym Connection::KeycodeToKeysym(uint32_t keycode, unsigned int modifiers) {
+uint32_t Connection::KeycodeToKeysym(KeyCode keycode,
+ uint32_t modifiers) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- XKeyEvent key_event{
- .type = KeyEvent::Press,
- .display = display_,
- .state = modifiers,
- .keycode = keycode,
- };
- ::KeySym keysym;
- XLookupString(&key_event, nullptr, 0, &keysym, nullptr);
- return static_cast<x11::KeySym>(keysym);
+ return keyboard_state_->KeycodeToKeysym(keycode, modifiers);
}
std::unique_ptr<Connection> Connection::Clone() const {
@@ -457,25 +349,18 @@ void Connection::DetachFromSequence() {
void Connection::Dispatch(Delegate* delegate) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(display_);
auto process_next_response = [&] {
- xcb_connection_t* connection = XGetXCBConnection(display_);
- auto request = std::move(requests_.front());
- requests_.pop();
-
- void* raw_reply = nullptr;
- xcb_generic_error_t* raw_error = nullptr;
- xcb_poll_for_reply(connection, request.sequence, &raw_reply, &raw_error);
+ DCHECK(!requests_.empty());
+ DCHECK(requests_.front().have_response);
- scoped_refptr<MallocedRefCountedMemory> reply;
- if (raw_reply)
- reply = base::MakeRefCounted<MallocedRefCountedMemory>(raw_reply);
- std::move(request.callback).Run(reply, FutureBase::RawError{raw_error});
+ Request request = std::move(requests_.front());
+ requests_.pop();
+ std::move(request.callback).Run(request.reply, request.error);
};
auto process_next_event = [&] {
- DCHECK(!events_.empty());
+ DCHECK(HasNextEvent());
Event event = std::move(events_.front());
events_.pop_front();
@@ -488,7 +373,7 @@ void Connection::Dispatch(Delegate* delegate) {
Flush();
ReadResponses();
- if (HasNextResponse() && !events_.empty()) {
+ if (HasNextResponse() && HasNextEvent()) {
if (!events_.front().sequence_valid()) {
process_next_event();
continue;
@@ -506,7 +391,7 @@ void Connection::Dispatch(Delegate* delegate) {
process_next_event();
} else if (HasNextResponse()) {
process_next_response();
- } else if (!events_.empty()) {
+ } else if (HasNextEvent()) {
process_next_event();
} else {
break;
@@ -514,6 +399,18 @@ void Connection::Dispatch(Delegate* delegate) {
}
}
+Connection::ErrorHandler Connection::SetErrorHandler(ErrorHandler new_handler) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ return std::exchange(error_handler_, new_handler);
+}
+
+void Connection::SetIOErrorHandler(IOErrorHandler new_handler) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ io_error_handler_ = std::move(new_handler);
+}
+
void Connection::InitRootDepthAndVisual() {
for (auto& depth : default_screen_->allowed_depths) {
for (auto& visual : depth.visuals) {
@@ -543,13 +440,13 @@ void Connection::PreDispatchEvent(const Event& event) {
setup_.min_keycode = mapping->first_keycode;
setup_.max_keycode = static_cast<x11::KeyCode>(
static_cast<int>(mapping->first_keycode) + mapping->count - 1);
- ResetKeyboardState();
+ keyboard_state_->UpdateMapping();
}
}
if (auto* notify = event.As<x11::Xkb::NewKeyboardNotifyEvent>()) {
setup_.min_keycode = notify->minKeyCode;
setup_.max_keycode = notify->maxKeyCode;
- ResetKeyboardState();
+ keyboard_state_->UpdateMapping();
}
// This is adapted from XRRUpdateConfiguration.
@@ -587,141 +484,23 @@ int Connection::ScreenIndexFromRootWindow(Window root) const {
return -1;
}
-void Connection::ResetKeyboardState() {
- uint8_t min_keycode = static_cast<uint8_t>(setup_.min_keycode);
- uint8_t max_keycode = static_cast<uint8_t>(setup_.max_keycode);
- uint8_t count = max_keycode - min_keycode + 1;
- auto keyboard_future = GetKeyboardMapping({setup_.min_keycode, count});
- auto modifier_future = GetModifierMapping({});
- Flush();
- if (auto reply = keyboard_future.Sync())
- keyboard_mapping_ = std::move(*reply.reply);
- if (auto reply = modifier_future.Sync())
- modifier_mapping_ = std::move(*reply.reply);
-
- for (uint8_t i = 0; i < modifier_mapping_.keycodes_per_modifier; i++) {
- // Lock modifiers are in the second row of the matrix
- size_t index = 2 * modifier_mapping_.keycodes_per_modifier + i;
- for (uint8_t j = 0; j < keyboard_mapping_.keysyms_per_keycode; j++) {
- auto sym = static_cast<uint32_t>(
- KeyCodetoKeySym(modifier_mapping_.keycodes[index], j));
- if (sym == XK_Caps_Lock || sym == XK_ISO_Lock) {
- lock_meaning_ = XK_Caps_Lock;
- break;
- }
- if (sym == XK_Shift_Lock)
- lock_meaning_ = XK_Shift_Lock;
- }
- }
-
- // Mod<n> is at row (n + 2) of the matrix. This iterates from Mod1 to Mod5.
- for (int mod = 3; mod < 8; mod++) {
- for (size_t i = 0; i < modifier_mapping_.keycodes_per_modifier; i++) {
- size_t index = mod * modifier_mapping_.keycodes_per_modifier + i;
- for (uint8_t j = 0; j < keyboard_mapping_.keysyms_per_keycode; j++) {
- auto sym = static_cast<uint32_t>(
- KeyCodetoKeySym(modifier_mapping_.keycodes[index], j));
- if (sym == XK_Mode_switch)
- mode_switch_ |= 1 << mod;
- if (sym == XK_Num_Lock)
- num_lock_ |= 1 << mod;
- }
- }
- }
+std::unique_ptr<Error> Connection::ParseError(
+ FutureBase::RawError error_bytes) {
+ if (!error_bytes)
+ return nullptr;
+ struct ErrorHeader {
+ uint8_t response_type;
+ uint8_t error_code;
+ uint16_t sequence;
+ };
+ auto error_code = error_bytes->front_as<ErrorHeader>()->error_code;
+ if (auto parser = error_parsers_[error_code])
+ return parser(error_bytes);
+ return std::make_unique<UnknownError>(error_bytes);
}
-// Ported from xcb_key_symbols_get_keysym
-// https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms/-/blob/691515491a4a3c119adc6c769c29de264b3f3806/keysyms/keysyms.c#L189
-KeySym Connection::KeyCodetoKeySym(KeyCode keycode, int column) const {
- uint8_t key = static_cast<uint8_t>(keycode);
- uint8_t n_keysyms = keyboard_mapping_.keysyms_per_keycode;
-
- uint8_t min_key = static_cast<uint8_t>(setup_.min_keycode);
- uint8_t max_key = static_cast<uint8_t>(setup_.max_keycode);
- if (column < 0 || (column >= n_keysyms && column > 3) || key < min_key ||
- key > max_key) {
- return kNoSymbol;
- }
-
- const auto* syms = &keyboard_mapping_.keysyms[(key - min_key) * n_keysyms];
- if (column < 4) {
- if (column > 1) {
- while ((n_keysyms > 2) && (syms[n_keysyms - 1] == kNoSymbol))
- n_keysyms--;
- if (n_keysyms < 3)
- column -= 2;
- }
- if ((n_keysyms <= (column | 1)) || (syms[column | 1] == kNoSymbol)) {
- KeySym lsym, usym;
- ConvertCase(syms[column & ~1], &lsym, &usym);
- if (!(column & 1))
- return lsym;
- if (usym == lsym)
- return kNoSymbol;
- return usym;
- }
- }
- return syms[column];
-}
-
-// Ported from _XTranslateKey:
-// https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/2b7598221d87049d03e9a95fcb541c37c8728184/src/KeyBind.c#L761
-KeySym Connection::TranslateKey(uint32_t key, unsigned int modifiers) const {
- constexpr auto kShiftMask = static_cast<unsigned int>(x11::ModMask::Shift);
- constexpr auto kLockMask = static_cast<unsigned int>(x11::ModMask::Lock);
-
- uint8_t min_key = static_cast<uint8_t>(setup_.min_keycode);
- uint8_t max_key = static_cast<uint8_t>(setup_.max_keycode);
- if (key < min_key || key > max_key)
- return kNoSymbol;
-
- uint8_t n_keysyms = keyboard_mapping_.keysyms_per_keycode;
- if (!n_keysyms)
- return {};
- const auto* syms = &keyboard_mapping_.keysyms[(key - min_key) * n_keysyms];
- while ((n_keysyms > 2) && (syms[n_keysyms - 1] == kNoSymbol))
- n_keysyms--;
- if ((n_keysyms > 2) && (modifiers & mode_switch_)) {
- syms += 2;
- n_keysyms -= 2;
- }
-
- if ((modifiers & num_lock_) &&
- (n_keysyms > 1 &&
- (IsXKeypadKey(syms[1]) || IsPrivateXKeypadKey(syms[1])))) {
- if ((modifiers & kShiftMask) ||
- ((modifiers & kLockMask) && (lock_meaning_ == XK_Shift_Lock))) {
- return syms[0];
- }
- return syms[1];
- }
-
- KeySym lower;
- KeySym upper;
- if (!(modifiers & kShiftMask) &&
- (!(modifiers & kLockMask) ||
- (static_cast<x11::KeySym>(lock_meaning_) == kNoSymbol))) {
- if ((n_keysyms == 1) || (syms[1] == kNoSymbol)) {
- ConvertCase(syms[0], &lower, &upper);
- return lower;
- }
- return syms[0];
- }
-
- if (!(modifiers & kLockMask) || (lock_meaning_ != XK_Caps_Lock)) {
- if ((n_keysyms == 1) || ((upper = syms[1]) == kNoSymbol))
- ConvertCase(syms[0], &lower, &upper);
- return upper;
- }
-
- KeySym sym;
- if ((n_keysyms == 1) || ((sym = syms[1]) == kNoSymbol))
- sym = syms[0];
- ConvertCase(sym, &lower, &upper);
- if (!(modifiers & kShiftMask) && (sym != syms[0]) &&
- ((sym != upper) || (lower == upper)))
- ConvertCase(syms[0], &lower, &upper);
- return upper;
+uint32_t Connection::GenerateIdImpl() {
+ return xcb_generate_id(connection_);
}
} // namespace x11
diff --git a/chromium/ui/gfx/x/connection.h b/chromium/ui/gfx/x/connection.h
index 1e0fa6c2300..6b16ae22dc2 100644
--- a/chromium/ui/gfx/x/connection.h
+++ b/chromium/ui/gfx/x/connection.h
@@ -5,22 +5,30 @@
#ifndef UI_GFX_X_CONNECTION_H_
#define UI_GFX_X_CONNECTION_H_
-#include <list>
#include <queue>
#include "base/component_export.h"
+#include "base/containers/circular_deque.h"
#include "base/sequence_checker.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/x/event.h"
#include "ui/gfx/x/extension_manager.h"
+#include "ui/gfx/x/xlib_support.h"
#include "ui/gfx/x/xproto.h"
+typedef struct xcb_connection_t xcb_connection_t;
+
namespace x11 {
+class KeyboardState;
+
// Represents a socket to the X11 server.
class COMPONENT_EXPORT(X11) Connection : public XProto,
public ExtensionManager {
public:
+ using ErrorHandler = base::RepeatingCallback<void(const Error*, const char*)>;
+ using IOErrorHandler = base::OnceClosure;
+
class Delegate {
public:
virtual bool ShouldContinueStream() const = 0;
@@ -47,12 +55,16 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
Connection(const Connection&) = delete;
Connection(Connection&&) = delete;
- XDisplay* display() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return display_;
- }
xcb_connection_t* XcbConnection();
+ // Obtain an Xlib display that's connected to the same server as |this|. This
+ // is meant to be used only for compatibility with components like GLX,
+ // Vulkan, and VAAPI. The underlying socket is not shared, so synchronization
+ // with |this| may be necessary. The |type| parameter can be used to achieve
+ // synchronization. The returned wrapper should not be saved.
+ XlibDisplayWrapper GetXlibDisplay(
+ XlibDisplayType type = XlibDisplayType::kNormal);
+
uint32_t extended_max_request_length() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return extended_max_request_length_;
@@ -85,12 +97,14 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
const std::string& DisplayString() const;
+ std::string GetConnectionHostname() const;
+
int DefaultScreenId() const;
template <typename T>
T GenerateId() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return static_cast<T>(xcb_generate_id(XcbConnection()));
+ return static_cast<T>(GenerateIdImpl());
}
// Is the connection up and error-free?
@@ -113,21 +127,28 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
Event WaitForNextEvent();
// Are there any events, errors, or replies already buffered?
- bool HasPendingResponses() const;
+ bool HasPendingResponses();
// Dispatch any buffered events, errors, or replies.
void Dispatch(Delegate* delegate);
+ // Returns the old error handler.
+ ErrorHandler SetErrorHandler(ErrorHandler new_handler);
+
+ void SetIOErrorHandler(IOErrorHandler new_handler);
+
// Returns the visual data for |id|, or nullptr if the visual with that ID
// doesn't exist or only exists on a non-default screen.
const VisualInfo* GetVisualInfoFromId(VisualId id) const;
- KeyCode KeysymToKeycode(KeySym keysym);
+ KeyCode KeysymToKeycode(uint32_t keysym) const;
- KeySym KeycodeToKeysym(uint32_t keycode, unsigned int modifiers);
+ uint32_t KeycodeToKeysym(KeyCode keycode, uint32_t modifiers) const;
- // Access the event buffer. Clients can add, delete, or modify events.
- std::list<Event>& events() {
+ // Access the event buffer. Clients may modify the queue, including
+ // "deleting" events by setting events[i] = x11::Event(), which will
+ // guarantee all calls to x11::Event::As() will return nullptr.
+ base::circular_deque<Event>& events() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return events_;
}
@@ -153,25 +174,32 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
const unsigned int sequence;
FutureBase::ResponseCallback callback;
+ bool have_response = false;
+ FutureBase::RawReply reply;
+ FutureBase::RawError error;
};
void InitRootDepthAndVisual();
void AddRequest(unsigned int sequence, FutureBase::ResponseCallback callback);
- bool HasNextResponse() const;
+ bool HasNextResponse();
+
+ bool HasNextEvent();
void PreDispatchEvent(const Event& event);
int ScreenIndexFromRootWindow(x11::Window root) const;
- void ResetKeyboardState();
+ // This function is implemented in the generated read_error.cc.
+ void InitErrorParsers();
- KeySym KeyCodetoKeySym(KeyCode keycode, int column) const;
+ std::unique_ptr<Error> ParseError(FutureBase::RawError error_bytes);
- KeySym TranslateKey(uint32_t keycode, unsigned int modifiers) const;
+ uint32_t GenerateIdImpl();
- XDisplay* const display_;
+ xcb_connection_t* connection_ = nullptr;
+ std::unique_ptr<XlibDisplay> xlib_display_;
bool synchronous_ = false;
bool syncing_ = false;
@@ -187,17 +215,19 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
std::unordered_map<VisualId, VisualInfo> default_screen_visuals_;
- // Keyboard state.
- GetKeyboardMappingReply keyboard_mapping_;
- GetModifierMappingReply modifier_mapping_;
- uint16_t lock_meaning_ = 0;
- uint8_t mode_switch_ = 0;
- uint8_t num_lock_ = 0;
+ std::unique_ptr<KeyboardState> keyboard_state_;
- std::list<Event> events_;
+ base::circular_deque<Event> events_;
std::queue<Request> requests_;
+ using ErrorParser =
+ std::unique_ptr<Error> (*)(FutureBase::RawError error_bytes);
+ std::array<ErrorParser, 256> error_parsers_{};
+
+ ErrorHandler error_handler_;
+ IOErrorHandler io_error_handler_;
+
SEQUENCE_CHECKER(sequence_checker_);
};
diff --git a/chromium/ui/gfx/x/connection_unittest.cc b/chromium/ui/gfx/x/connection_unittest.cc
index 42e581c69cc..4f140e05aea 100644
--- a/chromium/ui/gfx/x/connection_unittest.cc
+++ b/chromium/ui/gfx/x/connection_unittest.cc
@@ -37,13 +37,13 @@ Window CreateWindow(Connection* connection) {
TEST(X11ConnectionTest, Basic) {
Connection connection;
ASSERT_TRUE(connection.XcbConnection());
- EXPECT_FALSE(xcb_connection_has_error(connection.XcbConnection()));
+ EXPECT_TRUE(connection.Ready());
}
TEST(X11ConnectionTest, Request) {
Connection connection;
ASSERT_TRUE(connection.XcbConnection());
- EXPECT_FALSE(xcb_connection_has_error(connection.XcbConnection()));
+ EXPECT_TRUE(connection.Ready());
Window window = CreateWindow(&connection);
@@ -63,7 +63,7 @@ TEST(X11ConnectionTest, Request) {
TEST(X11ConnectionTest, Event) {
Connection connection;
ASSERT_TRUE(connection.XcbConnection());
- EXPECT_FALSE(xcb_connection_has_error(connection.XcbConnection()));
+ EXPECT_TRUE(connection.Ready());
Window window = CreateWindow(&connection);
@@ -95,15 +95,17 @@ TEST(X11ConnectionTest, Event) {
TEST(X11ConnectionTest, Error) {
Connection connection;
ASSERT_TRUE(connection.XcbConnection());
- EXPECT_FALSE(xcb_connection_has_error(connection.XcbConnection()));
+ EXPECT_TRUE(connection.Ready());
Window invalid_window = connection.GenerateId<Window>();
auto geometry = connection.GetGeometry({invalid_window}).Sync();
ASSERT_FALSE(geometry);
- xcb_generic_error_t* error = geometry.error.get();
- EXPECT_EQ(error->error_code, XCB_DRAWABLE);
- EXPECT_EQ(error->resource_id, static_cast<uint32_t>(invalid_window));
+ auto* error = geometry.error.get();
+ ASSERT_TRUE(error);
+ // TODO(thomasanderson): Implement As<> for errors, similar to events.
+ auto* drawable_error = reinterpret_cast<x11::DrawableError*>(error);
+ EXPECT_EQ(drawable_error->bad_value, static_cast<uint32_t>(invalid_window));
}
} // namespace x11
diff --git a/chromium/ui/gfx/x/error.cc b/chromium/ui/gfx/x/error.cc
new file mode 100644
index 00000000000..f33de1a474a
--- /dev/null
+++ b/chromium/ui/gfx/x/error.cc
@@ -0,0 +1,13 @@
+// Copyright 2020 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 "ui/gfx/x/error.h"
+
+namespace x11 {
+
+Error::Error() = default;
+
+Error::~Error() = default;
+
+} // namespace x11
diff --git a/chromium/ui/gfx/x/error.h b/chromium/ui/gfx/x/error.h
new file mode 100644
index 00000000000..a9de90bfab5
--- /dev/null
+++ b/chromium/ui/gfx/x/error.h
@@ -0,0 +1,26 @@
+// Copyright 2020 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.
+
+#ifndef UI_GFX_X_ERROR_H_
+#define UI_GFX_X_ERROR_H_
+
+#include <string>
+
+#include "base/component_export.h"
+
+namespace x11 {
+
+// This class is a generic interface for X11 errors. Currently the only
+// functionality is printing the error as a human-readable string.
+class COMPONENT_EXPORT(X11) Error {
+ public:
+ Error();
+ virtual ~Error();
+
+ virtual std::string ToString() const = 0;
+};
+
+} // namespace x11
+
+#endif // UI_GFX_X_ERROR_H_
diff --git a/chromium/ui/gfx/x/event.cc b/chromium/ui/gfx/x/event.cc
index 41cd3649702..3d0637ca39b 100644
--- a/chromium/ui/gfx/x/event.cc
+++ b/chromium/ui/gfx/x/event.cc
@@ -19,19 +19,6 @@ namespace x11 {
Event::Event() = default;
-Event::Event(xcb_generic_event_t* xcb_event,
- x11::Connection* connection,
- bool sequence_valid)
- : Event(base::MakeRefCounted<x11::UnretainedRefCountedMemory>(xcb_event),
- connection,
- sequence_valid) {
- // Make sure the event is a fixed-size (32 bytes) event, otherwise
- // UnretainedRefCountedMemory may be unsafe to use if the event contains
- // variable-sized data.
- DCHECK_NE(xcb_event->response_type & ~x11::kSendEventMask,
- x11::GeGenericEvent::opcode);
-}
-
Event::Event(scoped_refptr<base::RefCountedMemory> event_bytes,
x11::Connection* connection,
bool sequence_valid) {
diff --git a/chromium/ui/gfx/x/event.h b/chromium/ui/gfx/x/event.h
index 7e3d41dc7ce..c13e94228b6 100644
--- a/chromium/ui/gfx/x/event.h
+++ b/chromium/ui/gfx/x/event.h
@@ -38,9 +38,7 @@ class COMPONENT_EXPORT(X11) Event {
}
Event();
- Event(xcb_generic_event_t* xcb_event,
- Connection* connection,
- bool sequence_valid = true);
+
// |event_bytes| is modified and will not be valid after this call.
// A copy is necessary if the original data is still needed.
Event(scoped_refptr<base::RefCountedMemory> event_bytes,
@@ -76,6 +74,8 @@ class COMPONENT_EXPORT(X11) Event {
*window_ = window;
}
+ bool Initialized() const { return deleter_; }
+
private:
friend void ReadEvent(Event* event,
Connection* connection,
diff --git a/chromium/ui/gfx/x/gen_xproto.py b/chromium/ui/gfx/x/gen_xproto.py
index 391779422fc..94df052aa4f 100644
--- a/chromium/ui/gfx/x/gen_xproto.py
+++ b/chromium/ui/gfx/x/gen_xproto.py
@@ -919,6 +919,14 @@ class GenXproto(FileWriter):
self.write('x11::Window* GetWindow() { return %s; }' % ret)
self.write()
+ def declare_error(self, error, name):
+ name = adjust_type_name(name[-1] + 'Error')
+ with Indent(self, 'struct %s : public x11::Error {' % name, '};'):
+ self.declare_fields(error.fields)
+ self.write()
+ self.write('std::string ToString() const override;')
+ self.write()
+
def declare_container(self, struct, struct_name):
name = struct_name[-1] + self.type_suffix(struct)
with Indent(self, 'struct %s {' % adjust_type_name(name), '};'):
@@ -1025,8 +1033,9 @@ class GenXproto(FileWriter):
self.write('Align(&buf, 4);')
self.write()
reply_has_fds = reply and any(field.isfd for field in reply.fields)
- self.write('return x11::SendRequest<%s>(connection_, &buf, %s);' %
- (reply_name, 'true' if reply_has_fds else 'false'))
+ self.write(
+ 'return x11::SendRequest<%s>(connection_, &buf, %s, "%s");' %
+ (reply_name, 'true' if reply_has_fds else 'false', prefix))
self.write()
if not reply:
@@ -1066,6 +1075,29 @@ class GenXproto(FileWriter):
self.write('DCHECK_LE(buf.offset, 32ul);')
self.write()
+ def define_error(self, error, name):
+ self.namespace = ['x11']
+ name = self.qualtype(error, name)
+ with Indent(self, 'std::string %s::ToString() const {' % name, '}'):
+ self.write('std::stringstream ss_;')
+ self.write('ss_ << "x11::%s{";' % name)
+ fields = [field for field in error.fields if field.visible]
+ for i, field in enumerate(fields):
+ terminator = '' if i == len(fields) - 1 else ' << ", "'
+ self.write('ss_ << ".%s = " << static_cast<uint64_t>(%s)%s;' %
+ (field.field_name, field.field_name, terminator))
+ self.write('ss_ << "}";')
+ self.write('return ss_.str();')
+ self.write()
+ self.write('template <>')
+ self.write('void ReadError<%s>(' % name)
+ with Indent(self, ' %s* error_, ReadBuffer* buffer) {' % name, '}'):
+ self.write('auto& buf = *buffer;')
+ self.write()
+ self.is_read = True
+ self.copy_container(error, '(*error_)')
+ self.write('DCHECK_LE(buf.offset, 32ul);')
+
def define_type(self, item, name):
if name in READ_SPECIAL:
self.read_special_container(item, name)
@@ -1075,6 +1107,8 @@ class GenXproto(FileWriter):
self.define_request(item)
elif item.is_event:
self.define_event(item, name)
+ elif isinstance(item, self.xcbgen.xtypes.Error):
+ self.define_error(item, name)
def declare_type(self, item, name):
if item.is_union:
@@ -1083,6 +1117,8 @@ class GenXproto(FileWriter):
self.declare_request(item)
elif item.is_event:
self.declare_event(item, name)
+ elif isinstance(item, self.xcbgen.xtypes.Error):
+ self.declare_error(item, name)
elif item.is_container:
self.declare_container(item, name)
elif isinstance(item, self.xcbgen.xtypes.Enum):
@@ -1314,6 +1350,7 @@ class GenXproto(FileWriter):
self.write('#include "base/memory/scoped_refptr.h"')
self.write('#include "base/optional.h"')
self.write('#include "base/files/scoped_file.h"')
+ self.write('#include "ui/gfx/x/error.h"')
self.write('#include "ui/gfx/x/xproto_types.h"')
imports = set(self.module.direct_imports)
if self.module.namespace.is_ext:
@@ -1493,6 +1530,8 @@ class GenExtensionManager(FileWriter):
self.write(
'auto %s_future = conn->QueryExtension({"%s"});' %
(extension.proto, extension.module.namespace.ext_xname))
+ # Flush so all requests are sent before waiting on any replies.
+ self.write('conn->Flush();')
self.write()
for extension in self.extensions:
name = extension.proto
@@ -1578,6 +1617,8 @@ class GenReadEvent(FileWriter):
self.file = open(os.path.join(self.gen_dir, 'read_event.cc'), 'w')
self.write('#include "ui/gfx/x/event.h"')
self.write()
+ self.write('#include <xcb/xcb.h>')
+ self.write()
self.write('#include "ui/gfx/x/connection.h"')
for genproto in self.genprotos:
self.write('#include "ui/gfx/x/%s.h"' % genproto.proto)
@@ -1601,6 +1642,90 @@ class GenReadEvent(FileWriter):
self.write('} // namespace x11')
+class GenReadError(FileWriter):
+ def __init__(self, gen_dir, genprotos, xcbgen):
+ FileWriter.__init__(self)
+
+ self.gen_dir = gen_dir
+ self.genprotos = genprotos
+ self.xcbgen = xcbgen
+
+ def get_errors_for_proto(self, proto):
+ errors = {}
+ for _, item in proto.module.all:
+ if isinstance(item, self.xcbgen.xtypes.Error):
+ for name in item.opcodes:
+ id = int(item.opcodes[name])
+ if id < 0:
+ continue
+ name = [adjust_type_name(part) for part in name[1:]]
+ typename = '::'.join(name) + 'Error'
+ errors[id] = typename
+ return errors
+
+ def gen_errors_for_proto(self, errors, proto):
+ if proto.module.namespace.is_ext:
+ cond = 'if (%s().present()) {' % proto.proto
+ first_error = '%s().first_error()' % proto.proto
+ else:
+ cond = '{'
+ first_error = '0'
+ with Indent(self, cond, '}'):
+ self.write('uint8_t first_error = %s;' % first_error)
+ for id, name in sorted(errors.items()):
+ with Indent(self, '{', '}'):
+ self.write('auto error_code = first_error + %d;' % id)
+ self.write('auto parse = MakeError<%s>;' % name)
+ self.write('add_parser(error_code, first_error, parse);')
+ self.write()
+
+ def gen_init_error_parsers(self):
+ self.write('uint8_t first_errors[256];')
+ self.write('memset(first_errors, 0, sizeof(first_errors));')
+ self.write()
+ args = 'uint8_t error_code, uint8_t first_error, ErrorParser parser'
+ with Indent(self, 'auto add_parser = [&](%s) {' % args, '};'):
+ cond = ('!error_parsers_[error_code] || ' +
+ 'first_error > first_errors[error_code]')
+ with Indent(self, 'if (%s) {' % cond, '}'):
+ self.write('first_errors[error_code] = error_code;')
+ self.write('error_parsers_[error_code] = parser;')
+ self.write()
+ for proto in self.genprotos:
+ errors = self.get_errors_for_proto(proto)
+ if errors:
+ self.gen_errors_for_proto(errors, proto)
+
+ def gen_source(self):
+ self.file = open(os.path.join(self.gen_dir, 'read_error.cc'), 'w')
+ self.write('#include "ui/gfx/x/connection.h"')
+ self.write('#include "ui/gfx/x/error.h"')
+ self.write('#include "ui/gfx/x/xproto_internal.h"')
+ self.write()
+ for genproto in self.genprotos:
+ self.write('#include "ui/gfx/x/%s.h"' % genproto.proto)
+ self.write()
+ self.write('namespace x11 {')
+ self.write()
+ self.write('namespace {')
+ self.write()
+ self.write('template <typename T>')
+ sig = 'std::unique_ptr<Error> MakeError(FutureBase::RawError error_)'
+ with Indent(self, '%s {' % sig, '}'):
+ self.write('ReadBuffer buf(error_);')
+ self.write('auto error = std::make_unique<T>();')
+ self.write('ReadError(error.get(), &buf);')
+ self.write('return error;')
+ self.write()
+ self.write('} // namespace')
+ self.write()
+ with Indent(self, 'void Connection::InitErrorParsers() {', '}'):
+ self.gen_init_error_parsers()
+
+ self.write()
+ self.write('} // namespace x11')
+
+
def main():
parser = argparse.ArgumentParser()
parser.add_argument('xcbproto_dir', type=str)
@@ -1639,8 +1764,9 @@ def main():
gen_extension_manager.gen_header()
gen_extension_manager.gen_source()
- gen_read_event = GenReadEvent(args.gen_dir, genprotos)
- gen_read_event.gen_source()
+ GenReadEvent(args.gen_dir, genprotos).gen_source()
+
+ GenReadError(args.gen_dir, genprotos, xcbgen).gen_source()
return 0
diff --git a/chromium/ui/gfx/x/keyboard_state.cc b/chromium/ui/gfx/x/keyboard_state.cc
new file mode 100644
index 00000000000..3ca1e8084bc
--- /dev/null
+++ b/chromium/ui/gfx/x/keyboard_state.cc
@@ -0,0 +1,136 @@
+// Copyright 2020 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 "ui/gfx/x/keyboard_state.h"
+
+#include "base/i18n/case_conversion.h"
+#include "ui/gfx/x/connection.h"
+#include "ui/gfx/x/keysyms/keysyms.h"
+#include "ui/gfx/x/xkb.h"
+#include "ui/gfx/x/xproto.h"
+
+namespace x11 {
+
+namespace {
+
+constexpr KeySym kNoSymbol = static_cast<KeySym>(0);
+
+void ConvertCaseImpl(uint32_t sym, uint32_t* lower, uint32_t* upper);
+
+void ConvertCase(KeySym sym, KeySym* lower, KeySym* upper) {
+ uint32_t lower32;
+ uint32_t upper32;
+ ConvertCaseImpl(static_cast<uint32_t>(sym), &lower32, &upper32);
+ *lower = static_cast<KeySym>(lower32);
+ *upper = static_cast<KeySym>(upper32);
+}
+
+bool IsPublicOrPrivateKeypadKey(KeySym keysym) {
+ auto key = static_cast<uint32_t>(keysym);
+ return (key >= XK_KP_Space && key <= XK_KP_Equal) ||
+ (key >= 0x11000000 && key <= 0x1100FFFF);
+}
+
+int GetXkbGroupFromState(int state) {
+ return (state >> 13) & 0x3;
+}
+
+#include "third_party/libx11/src/KeyBind.c"
+#include "third_party/libx11/src/xkb/XKBBind.c"
+#include "third_party/libxcb-keysyms/keysyms/keysyms.c"
+
+} // namespace
+
+KeyboardState::KeyboardState() = default;
+
+KeyboardState::~KeyboardState() = default;
+
+// Non-XKB (core protocol) implementation of KeysymToKeycode and
+// KeycodeToKeysym.
+class CoreKeyboardState : public KeyboardState {
+ public:
+ explicit CoreKeyboardState(Connection* connection) : connection_(connection) {
+ UpdateMapping();
+ }
+
+ ~CoreKeyboardState() override = default;
+
+ KeyCode KeysymToKeycode(uint32_t keysym) const override {
+ auto min_keycode = static_cast<uint8_t>(connection_->setup().min_keycode);
+ auto max_keycode = static_cast<uint8_t>(connection_->setup().max_keycode);
+ int count = max_keycode - min_keycode + 1;
+ DCHECK_EQ(count * keyboard_mapping_.keysyms_per_keycode,
+ static_cast<int>(keyboard_mapping_.keysyms.size()));
+ for (size_t i = 0; i < keyboard_mapping_.keysyms.size(); i++) {
+ auto keycode = min_keycode + i / keyboard_mapping_.keysyms_per_keycode;
+ if (keyboard_mapping_.keysyms[i] == static_cast<x11::KeySym>(keysym))
+ return static_cast<KeyCode>(keycode);
+ }
+ return {};
+ }
+
+ uint32_t KeycodeToKeysym(KeyCode keycode, uint32_t modifiers) const override {
+ auto sym = static_cast<uint32_t>(KeycodeToKeysymCoreImpl(
+ keycode, modifiers, connection_, keyboard_mapping_, lock_meaning_,
+ mode_switch_, num_lock_));
+ return sym == XK_VoidSymbol ? 0 : sym;
+ }
+
+ private:
+ void UpdateMapping() override {
+ UpdateMappingImpl(connection_, &keyboard_mapping_, &lock_meaning_,
+ &mode_switch_, &num_lock_);
+ }
+
+ x11::Connection* const connection_;
+ GetKeyboardMappingReply keyboard_mapping_;
+ uint16_t lock_meaning_ = 0;
+ uint8_t mode_switch_ = 0;
+ uint8_t num_lock_ = 0;
+};
+
+// XKB implementation of KeysymToKeycode and KeycodeToKeysym.
+class XkbKeyboardState : public KeyboardState {
+ public:
+ explicit XkbKeyboardState(Connection* connection) : connection_(connection) {
+ UpdateMapping();
+ }
+
+ ~XkbKeyboardState() override = default;
+
+ KeyCode KeysymToKeycode(uint32_t keysym) const override {
+ int first_keycode = static_cast<int>(map_.firstKeySym);
+ for (int keycode = 0; keycode < map_.nKeySyms; keycode++) {
+ for (auto sym : map_.syms_rtrn->at(keycode).syms) {
+ if (static_cast<uint32_t>(sym) == keysym)
+ return static_cast<KeyCode>(keycode + first_keycode);
+ }
+ }
+ return {};
+ }
+
+ uint32_t KeycodeToKeysym(KeyCode key, uint32_t modifiers) const override {
+ return KeycodeToKeysymXkbImpl(key, modifiers, map_);
+ }
+
+ private:
+ void UpdateMapping() override {
+ auto future = connection_->xkb().GetMap(
+ {static_cast<Xkb::DeviceSpec>(Xkb::Id::UseCoreKbd),
+ Xkb::MapPart::KeyTypes | Xkb::MapPart::KeySyms});
+ if (auto response = future.Sync())
+ map_ = std::move(*response.reply);
+ }
+
+ x11::Connection* const connection_;
+ Xkb::GetMapReply map_;
+};
+
+std::unique_ptr<KeyboardState> CreateKeyboardState(Connection* connection) {
+ if (connection->xkb().present())
+ return std::make_unique<XkbKeyboardState>(connection);
+ return std::make_unique<CoreKeyboardState>(connection);
+}
+
+} // namespace x11
diff --git a/chromium/ui/gfx/x/keyboard_state.h b/chromium/ui/gfx/x/keyboard_state.h
new file mode 100644
index 00000000000..d28fe595f39
--- /dev/null
+++ b/chromium/ui/gfx/x/keyboard_state.h
@@ -0,0 +1,37 @@
+// Copyright 2020 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.
+
+#ifndef UI_GFX_X_KEYBOARD_STATE_H_
+#define UI_GFX_X_KEYBOARD_STATE_H_
+
+#include <memory>
+
+#include "ui/gfx/x/xproto.h"
+
+namespace x11 {
+
+class Connection;
+
+// This is an interface used by Connection to manage conversion between keycodes
+// (8 bit values) and keysyms (32 bit values).
+class KeyboardState {
+ public:
+ KeyboardState();
+ virtual ~KeyboardState();
+
+ virtual KeyCode KeysymToKeycode(uint32_t keysym) const = 0;
+ virtual uint32_t KeycodeToKeysym(KeyCode keycode,
+ uint32_t modifiers) const = 0;
+
+ private:
+ friend class Connection;
+
+ virtual void UpdateMapping() = 0;
+};
+
+std::unique_ptr<KeyboardState> CreateKeyboardState(Connection* connection);
+
+} // namespace x11
+
+#endif // UI_GFX_X_KEYBOARD_STATE_H_
diff --git a/chromium/ui/gfx/x/keysyms/keysyms.h b/chromium/ui/gfx/x/keysyms/keysyms.h
index 4d5fbcbcedb..c43ca1a4072 100644
--- a/chromium/ui/gfx/x/keysyms/keysyms.h
+++ b/chromium/ui/gfx/x/keysyms/keysyms.h
@@ -7,1155 +7,6 @@
#include <cstdint>
-static constexpr uint32_t XK_space = 0x20;
-static constexpr uint32_t XK_exclam = 0x21;
-static constexpr uint32_t XK_quotedbl = 0x22;
-static constexpr uint32_t XK_numbersign = 0x23;
-static constexpr uint32_t XK_dollar = 0x24;
-static constexpr uint32_t XK_percent = 0x25;
-static constexpr uint32_t XK_ampersand = 0x26;
-static constexpr uint32_t XK_quoteright = 0x27;
-static constexpr uint32_t XK_parenleft = 0x28;
-static constexpr uint32_t XK_parenright = 0x29;
-static constexpr uint32_t XK_asterisk = 0x2A;
-static constexpr uint32_t XK_plus = 0x2B;
-static constexpr uint32_t XK_comma = 0x2C;
-static constexpr uint32_t XK_minus = 0x2D;
-static constexpr uint32_t XK_period = 0x2E;
-static constexpr uint32_t XK_slash = 0x2F;
-static constexpr uint32_t XK_0 = 0x30;
-static constexpr uint32_t XK_1 = 0x31;
-static constexpr uint32_t XK_2 = 0x32;
-static constexpr uint32_t XK_3 = 0x33;
-static constexpr uint32_t XK_4 = 0x34;
-static constexpr uint32_t XK_5 = 0x35;
-static constexpr uint32_t XK_6 = 0x36;
-static constexpr uint32_t XK_7 = 0x37;
-static constexpr uint32_t XK_8 = 0x38;
-static constexpr uint32_t XK_9 = 0x39;
-static constexpr uint32_t XK_colon = 0x3A;
-static constexpr uint32_t XK_semicolon = 0x3B;
-static constexpr uint32_t XK_less = 0x3C;
-static constexpr uint32_t XK_equal = 0x3D;
-static constexpr uint32_t XK_greater = 0x3E;
-static constexpr uint32_t XK_question = 0x3F;
-static constexpr uint32_t XK_at = 0x40;
-static constexpr uint32_t XK_A = 0x41;
-static constexpr uint32_t XK_Z = 0x5A;
-static constexpr uint32_t XK_bracketleft = 0x5B;
-static constexpr uint32_t XK_backslash = 0x5C;
-static constexpr uint32_t XK_bracketright = 0x5D;
-static constexpr uint32_t XK_asciicircum = 0x5E;
-static constexpr uint32_t XK_underscore = 0x5F;
-static constexpr uint32_t XK_quoteleft = 0x60;
-static constexpr uint32_t XK_a = 0x61;
-static constexpr uint32_t XK_z = 0x7A;
-static constexpr uint32_t XK_braceleft = 0x7B;
-static constexpr uint32_t XK_bar = 0x7C;
-static constexpr uint32_t XK_braceright = 0x7D;
-static constexpr uint32_t XK_asciitilde = 0x7E;
-static constexpr uint32_t XK_exclamdown = 0xA1;
-static constexpr uint32_t XK_brokenbar = 0xA6;
-static constexpr uint32_t XK_guillemotleft = 0xAB;
-static constexpr uint32_t XK_degree = 0xB0;
-static constexpr uint32_t XK_periodcentered = 0xB7;
-static constexpr uint32_t XK_guillemotright = 0xBB;
-static constexpr uint32_t XK_questiondown = 0xBF;
-static constexpr uint32_t XK_Agrave = 0xC0;
-static constexpr uint32_t XK_Odiaeresis = 0xD6;
-static constexpr uint32_t XK_multiply = 0xD7;
-static constexpr uint32_t XK_Ooblique = 0xD8;
-static constexpr uint32_t XK_Ugrave = 0xD9;
-static constexpr uint32_t XK_Thorn = 0xDE;
-static constexpr uint32_t XK_agrave = 0xE0;
-static constexpr uint32_t XK_odiaeresis = 0xF6;
-static constexpr uint32_t XK_oslash = 0xF8;
-static constexpr uint32_t XK_ugrave = 0xF9;
-static constexpr uint32_t XK_thorn = 0xFE;
-static constexpr uint32_t XK_ydiaeresis = 0xFF;
-static constexpr uint32_t XK_Aogonek = 0x1A1;
-static constexpr uint32_t XK_breve = 0x1A2;
-static constexpr uint32_t XK_Lstroke = 0x1A3;
-static constexpr uint32_t XK_Lcaron = 0x1A5;
-static constexpr uint32_t XK_Sacute = 0x1A6;
-static constexpr uint32_t XK_Scaron = 0x1A9;
-static constexpr uint32_t XK_Scedilla = 0x1AA;
-static constexpr uint32_t XK_Tcaron = 0x1AB;
-static constexpr uint32_t XK_Zacute = 0x1AC;
-static constexpr uint32_t XK_Zcaron = 0x1AE;
-static constexpr uint32_t XK_Zabovedot = 0x1AF;
-static constexpr uint32_t XK_aogonek = 0x1B1;
-static constexpr uint32_t XK_ogonek = 0x1B2;
-static constexpr uint32_t XK_lstroke = 0x1B3;
-static constexpr uint32_t XK_lcaron = 0x1B5;
-static constexpr uint32_t XK_sacute = 0x1B6;
-static constexpr uint32_t XK_caron = 0x1B7;
-static constexpr uint32_t XK_scaron = 0x1B9;
-static constexpr uint32_t XK_scedilla = 0x1BA;
-static constexpr uint32_t XK_tcaron = 0x1BB;
-static constexpr uint32_t XK_zacute = 0x1BC;
-static constexpr uint32_t XK_doubleacute = 0x1BD;
-static constexpr uint32_t XK_zcaron = 0x1BE;
-static constexpr uint32_t XK_zabovedot = 0x1BF;
-static constexpr uint32_t XK_Racute = 0x1C0;
-static constexpr uint32_t XK_Abreve = 0x1C3;
-static constexpr uint32_t XK_Lacute = 0x1C5;
-static constexpr uint32_t XK_Cacute = 0x1C6;
-static constexpr uint32_t XK_Ccaron = 0x1C8;
-static constexpr uint32_t XK_Eogonek = 0x1CA;
-static constexpr uint32_t XK_Ecaron = 0x1CC;
-static constexpr uint32_t XK_Dcaron = 0x1CF;
-static constexpr uint32_t XK_Dstroke = 0x1D0;
-static constexpr uint32_t XK_Nacute = 0x1D1;
-static constexpr uint32_t XK_Ncaron = 0x1D2;
-static constexpr uint32_t XK_Odoubleacute = 0x1D5;
-static constexpr uint32_t XK_Rcaron = 0x1D8;
-static constexpr uint32_t XK_Uring = 0x1D9;
-static constexpr uint32_t XK_Udoubleacute = 0x1DB;
-static constexpr uint32_t XK_Tcedilla = 0x1DE;
-static constexpr uint32_t XK_racute = 0x1E0;
-static constexpr uint32_t XK_abreve = 0x1E3;
-static constexpr uint32_t XK_lacute = 0x1E5;
-static constexpr uint32_t XK_cacute = 0x1E6;
-static constexpr uint32_t XK_ccaron = 0x1E8;
-static constexpr uint32_t XK_eogonek = 0x1EA;
-static constexpr uint32_t XK_ecaron = 0x1EC;
-static constexpr uint32_t XK_dcaron = 0x1EF;
-static constexpr uint32_t XK_dstroke = 0x1F0;
-static constexpr uint32_t XK_nacute = 0x1F1;
-static constexpr uint32_t XK_ncaron = 0x1F2;
-static constexpr uint32_t XK_odoubleacute = 0x1F5;
-static constexpr uint32_t XK_rcaron = 0x1F8;
-static constexpr uint32_t XK_uring = 0x1F9;
-static constexpr uint32_t XK_udoubleacute = 0x1FB;
-static constexpr uint32_t XK_tcedilla = 0x1FE;
-static constexpr uint32_t XK_abovedot = 0x1FF;
-static constexpr uint32_t XK_Hstroke = 0x2A1;
-static constexpr uint32_t XK_Hcircumflex = 0x2A6;
-static constexpr uint32_t XK_Iabovedot = 0x2A9;
-static constexpr uint32_t XK_Gbreve = 0x2AB;
-static constexpr uint32_t XK_Jcircumflex = 0x2AC;
-static constexpr uint32_t XK_hstroke = 0x2B1;
-static constexpr uint32_t XK_hcircumflex = 0x2B6;
-static constexpr uint32_t XK_idotless = 0x2B9;
-static constexpr uint32_t XK_gbreve = 0x2BB;
-static constexpr uint32_t XK_jcircumflex = 0x2BC;
-static constexpr uint32_t XK_Cabovedot = 0x2C5;
-static constexpr uint32_t XK_Ccircumflex = 0x2C6;
-static constexpr uint32_t XK_Gabovedot = 0x2D5;
-static constexpr uint32_t XK_Gcircumflex = 0x2D8;
-static constexpr uint32_t XK_Ubreve = 0x2DD;
-static constexpr uint32_t XK_Scircumflex = 0x2DE;
-static constexpr uint32_t XK_cabovedot = 0x2E5;
-static constexpr uint32_t XK_ccircumflex = 0x2E6;
-static constexpr uint32_t XK_gabovedot = 0x2F5;
-static constexpr uint32_t XK_gcircumflex = 0x2F8;
-static constexpr uint32_t XK_ubreve = 0x2FD;
-static constexpr uint32_t XK_scircumflex = 0x2FE;
-static constexpr uint32_t XK_kra = 0x3A2;
-static constexpr uint32_t XK_Rcedilla = 0x3A3;
-static constexpr uint32_t XK_Itilde = 0x3A5;
-static constexpr uint32_t XK_Lcedilla = 0x3A6;
-static constexpr uint32_t XK_Emacron = 0x3AA;
-static constexpr uint32_t XK_Gcedilla = 0x3AB;
-static constexpr uint32_t XK_Tslash = 0x3AC;
-static constexpr uint32_t XK_rcedilla = 0x3B3;
-static constexpr uint32_t XK_itilde = 0x3B5;
-static constexpr uint32_t XK_lcedilla = 0x3B6;
-static constexpr uint32_t XK_emacron = 0x3BA;
-static constexpr uint32_t XK_gcedilla = 0x3BB;
-static constexpr uint32_t XK_tslash = 0x3BC;
-static constexpr uint32_t XK_ENG = 0x3BD;
-static constexpr uint32_t XK_eng = 0x3BF;
-static constexpr uint32_t XK_Amacron = 0x3C0;
-static constexpr uint32_t XK_Iogonek = 0x3C7;
-static constexpr uint32_t XK_Eabovedot = 0x3CC;
-static constexpr uint32_t XK_Imacron = 0x3CF;
-static constexpr uint32_t XK_Ncedilla = 0x3D1;
-static constexpr uint32_t XK_Omacron = 0x3D2;
-static constexpr uint32_t XK_Kcedilla = 0x3D3;
-static constexpr uint32_t XK_Uogonek = 0x3D9;
-static constexpr uint32_t XK_Utilde = 0x3DD;
-static constexpr uint32_t XK_Umacron = 0x3DE;
-static constexpr uint32_t XK_amacron = 0x3E0;
-static constexpr uint32_t XK_iogonek = 0x3E7;
-static constexpr uint32_t XK_eabovedot = 0x3EC;
-static constexpr uint32_t XK_imacron = 0x3EF;
-static constexpr uint32_t XK_ncedilla = 0x3F1;
-static constexpr uint32_t XK_omacron = 0x3F2;
-static constexpr uint32_t XK_kcedilla = 0x3F3;
-static constexpr uint32_t XK_uogonek = 0x3F9;
-static constexpr uint32_t XK_utilde = 0x3FD;
-static constexpr uint32_t XK_umacron = 0x3FE;
-static constexpr uint32_t XK_overline = 0x47E;
-static constexpr uint32_t XK_kana_fullstop = 0x4A1;
-static constexpr uint32_t XK_kana_openingbracket = 0x4A2;
-static constexpr uint32_t XK_kana_closingbracket = 0x4A3;
-static constexpr uint32_t XK_kana_comma = 0x4A4;
-static constexpr uint32_t XK_kana_conjunctive = 0x4A5;
-static constexpr uint32_t XK_kana_WO = 0x4A6;
-static constexpr uint32_t XK_kana_a = 0x4A7;
-static constexpr uint32_t XK_kana_i = 0x4A8;
-static constexpr uint32_t XK_kana_u = 0x4A9;
-static constexpr uint32_t XK_kana_e = 0x4AA;
-static constexpr uint32_t XK_kana_o = 0x4AB;
-static constexpr uint32_t XK_kana_ya = 0x4AC;
-static constexpr uint32_t XK_kana_yu = 0x4AD;
-static constexpr uint32_t XK_kana_yo = 0x4AE;
-static constexpr uint32_t XK_kana_tsu = 0x4AF;
-static constexpr uint32_t XK_prolongedsound = 0x4B0;
-static constexpr uint32_t XK_kana_A = 0x4B1;
-static constexpr uint32_t XK_kana_I = 0x4B2;
-static constexpr uint32_t XK_kana_U = 0x4B3;
-static constexpr uint32_t XK_kana_E = 0x4B4;
-static constexpr uint32_t XK_kana_O = 0x4B5;
-static constexpr uint32_t XK_kana_KA = 0x4B6;
-static constexpr uint32_t XK_kana_KI = 0x4B7;
-static constexpr uint32_t XK_kana_KU = 0x4B8;
-static constexpr uint32_t XK_kana_KE = 0x4B9;
-static constexpr uint32_t XK_kana_KO = 0x4BA;
-static constexpr uint32_t XK_kana_SA = 0x4BB;
-static constexpr uint32_t XK_kana_SHI = 0x4BC;
-static constexpr uint32_t XK_kana_SU = 0x4BD;
-static constexpr uint32_t XK_kana_SE = 0x4BE;
-static constexpr uint32_t XK_kana_SO = 0x4BF;
-static constexpr uint32_t XK_kana_TA = 0x4C0;
-static constexpr uint32_t XK_kana_CHI = 0x4C1;
-static constexpr uint32_t XK_kana_TSU = 0x4C2;
-static constexpr uint32_t XK_kana_TE = 0x4C3;
-static constexpr uint32_t XK_kana_TO = 0x4C4;
-static constexpr uint32_t XK_kana_NA = 0x4C5;
-static constexpr uint32_t XK_kana_NI = 0x4C6;
-static constexpr uint32_t XK_kana_NU = 0x4C7;
-static constexpr uint32_t XK_kana_NE = 0x4C8;
-static constexpr uint32_t XK_kana_NO = 0x4C9;
-static constexpr uint32_t XK_kana_HA = 0x4CA;
-static constexpr uint32_t XK_kana_HI = 0x4CB;
-static constexpr uint32_t XK_kana_FU = 0x4CC;
-static constexpr uint32_t XK_kana_HE = 0x4CD;
-static constexpr uint32_t XK_kana_HO = 0x4CE;
-static constexpr uint32_t XK_kana_MA = 0x4CF;
-static constexpr uint32_t XK_kana_MI = 0x4D0;
-static constexpr uint32_t XK_kana_MU = 0x4D1;
-static constexpr uint32_t XK_kana_ME = 0x4D2;
-static constexpr uint32_t XK_kana_MO = 0x4D3;
-static constexpr uint32_t XK_kana_YA = 0x4D4;
-static constexpr uint32_t XK_kana_YU = 0x4D5;
-static constexpr uint32_t XK_kana_YO = 0x4D6;
-static constexpr uint32_t XK_kana_RA = 0x4D7;
-static constexpr uint32_t XK_kana_RI = 0x4D8;
-static constexpr uint32_t XK_kana_RU = 0x4D9;
-static constexpr uint32_t XK_kana_RE = 0x4DA;
-static constexpr uint32_t XK_kana_RO = 0x4DB;
-static constexpr uint32_t XK_kana_WA = 0x4DC;
-static constexpr uint32_t XK_kana_N = 0x4DD;
-static constexpr uint32_t XK_voicedsound = 0x4DE;
-static constexpr uint32_t XK_semivoicedsound = 0x4DF;
-static constexpr uint32_t XK_Arabic_comma = 0x5AC;
-static constexpr uint32_t XK_Arabic_semicolon = 0x5BB;
-static constexpr uint32_t XK_Arabic_question_mark = 0x5BF;
-static constexpr uint32_t XK_Arabic_hamza = 0x5C1;
-static constexpr uint32_t XK_Arabic_maddaonalef = 0x5C2;
-static constexpr uint32_t XK_Arabic_hamzaonalef = 0x5C3;
-static constexpr uint32_t XK_Arabic_hamzaonwaw = 0x5C4;
-static constexpr uint32_t XK_Arabic_hamzaunderalef = 0x5C5;
-static constexpr uint32_t XK_Arabic_hamzaonyeh = 0x5C6;
-static constexpr uint32_t XK_Arabic_alef = 0x5C7;
-static constexpr uint32_t XK_Arabic_beh = 0x5C8;
-static constexpr uint32_t XK_Arabic_tehmarbuta = 0x5C9;
-static constexpr uint32_t XK_Arabic_teh = 0x5CA;
-static constexpr uint32_t XK_Arabic_theh = 0x5CB;
-static constexpr uint32_t XK_Arabic_jeem = 0x5CC;
-static constexpr uint32_t XK_Arabic_hah = 0x5CD;
-static constexpr uint32_t XK_Arabic_khah = 0x5CE;
-static constexpr uint32_t XK_Arabic_dal = 0x5CF;
-static constexpr uint32_t XK_Arabic_thal = 0x5D0;
-static constexpr uint32_t XK_Arabic_ra = 0x5D1;
-static constexpr uint32_t XK_Arabic_zain = 0x5D2;
-static constexpr uint32_t XK_Arabic_seen = 0x5D3;
-static constexpr uint32_t XK_Arabic_sheen = 0x5D4;
-static constexpr uint32_t XK_Arabic_sad = 0x5D5;
-static constexpr uint32_t XK_Arabic_dad = 0x5D6;
-static constexpr uint32_t XK_Arabic_tah = 0x5D7;
-static constexpr uint32_t XK_Arabic_zah = 0x5D8;
-static constexpr uint32_t XK_Arabic_ain = 0x5D9;
-static constexpr uint32_t XK_Arabic_ghain = 0x5DA;
-static constexpr uint32_t XK_Arabic_tatweel = 0x5E0;
-static constexpr uint32_t XK_Arabic_feh = 0x5E1;
-static constexpr uint32_t XK_Arabic_qaf = 0x5E2;
-static constexpr uint32_t XK_Arabic_kaf = 0x5E3;
-static constexpr uint32_t XK_Arabic_lam = 0x5E4;
-static constexpr uint32_t XK_Arabic_meem = 0x5E5;
-static constexpr uint32_t XK_Arabic_noon = 0x5E6;
-static constexpr uint32_t XK_Arabic_ha = 0x5E7;
-static constexpr uint32_t XK_Arabic_waw = 0x5E8;
-static constexpr uint32_t XK_Arabic_alefmaksura = 0x5E9;
-static constexpr uint32_t XK_Arabic_yeh = 0x5EA;
-static constexpr uint32_t XK_Arabic_fathatan = 0x5EB;
-static constexpr uint32_t XK_Arabic_dammatan = 0x5EC;
-static constexpr uint32_t XK_Arabic_kasratan = 0x5ED;
-static constexpr uint32_t XK_Arabic_fatha = 0x5EE;
-static constexpr uint32_t XK_Arabic_damma = 0x5EF;
-static constexpr uint32_t XK_Arabic_kasra = 0x5F0;
-static constexpr uint32_t XK_Arabic_shadda = 0x5F1;
-static constexpr uint32_t XK_Arabic_sukun = 0x5F2;
-static constexpr uint32_t XK_Serbian_dje = 0x6A1;
-static constexpr uint32_t XK_Macedonia_gje = 0x6A2;
-static constexpr uint32_t XK_Cyrillic_io = 0x6A3;
-static constexpr uint32_t XK_Ukrainian_ie = 0x6A4;
-static constexpr uint32_t XK_Macedonia_dse = 0x6A5;
-static constexpr uint32_t XK_Ukrainian_i = 0x6A6;
-static constexpr uint32_t XK_Ukrainian_yi = 0x6A7;
-static constexpr uint32_t XK_Cyrillic_je = 0x6A8;
-static constexpr uint32_t XK_Cyrillic_lje = 0x6A9;
-static constexpr uint32_t XK_Cyrillic_nje = 0x6AA;
-static constexpr uint32_t XK_Serbian_tshe = 0x6AB;
-static constexpr uint32_t XK_Macedonia_kje = 0x6AC;
-static constexpr uint32_t XK_Ukrainian_ghe_with_upturn = 0x6AD;
-static constexpr uint32_t XK_Byelorussian_shortu = 0x6AE;
-static constexpr uint32_t XK_Cyrillic_dzhe = 0x6AF;
-static constexpr uint32_t XK_Serbian_dze = 0x6AF;
-static constexpr uint32_t XK_numerosign = 0x6B0;
-static constexpr uint32_t XK_Serbian_DJE = 0x6B1;
-static constexpr uint32_t XK_Macedonia_GJE = 0x6B2;
-static constexpr uint32_t XK_Cyrillic_IO = 0x6B3;
-static constexpr uint32_t XK_Ukrainian_IE = 0x6B4;
-static constexpr uint32_t XK_Macedonia_DSE = 0x6B5;
-static constexpr uint32_t XK_Ukrainian_I = 0x6B6;
-static constexpr uint32_t XK_Ukrainian_YI = 0x6B7;
-static constexpr uint32_t XK_Cyrillic_JE = 0x6B8;
-static constexpr uint32_t XK_Cyrillic_LJE = 0x6B9;
-static constexpr uint32_t XK_Cyrillic_NJE = 0x6BA;
-static constexpr uint32_t XK_Serbian_TSHE = 0x6BB;
-static constexpr uint32_t XK_Macedonia_KJE = 0x6BC;
-static constexpr uint32_t XK_Ukrainian_GHE_WITH_UPTURN = 0x6BD;
-static constexpr uint32_t XK_Byelorussian_SHORTU = 0x6BE;
-static constexpr uint32_t XK_Cyrillic_DZHE = 0x6BF;
-static constexpr uint32_t XK_Serbian_DZE = 0x6BF;
-static constexpr uint32_t XK_Cyrillic_yu = 0x6C0;
-static constexpr uint32_t XK_Cyrillic_a = 0x6C1;
-static constexpr uint32_t XK_Cyrillic_be = 0x6C2;
-static constexpr uint32_t XK_Cyrillic_tse = 0x6C3;
-static constexpr uint32_t XK_Cyrillic_de = 0x6C4;
-static constexpr uint32_t XK_Cyrillic_ie = 0x6C5;
-static constexpr uint32_t XK_Cyrillic_ef = 0x6C6;
-static constexpr uint32_t XK_Cyrillic_ghe = 0x6C7;
-static constexpr uint32_t XK_Cyrillic_ha = 0x6C8;
-static constexpr uint32_t XK_Cyrillic_i = 0x6C9;
-static constexpr uint32_t XK_Cyrillic_shorti = 0x6CA;
-static constexpr uint32_t XK_Cyrillic_ka = 0x6CB;
-static constexpr uint32_t XK_Cyrillic_el = 0x6CC;
-static constexpr uint32_t XK_Cyrillic_em = 0x6CD;
-static constexpr uint32_t XK_Cyrillic_en = 0x6CE;
-static constexpr uint32_t XK_Cyrillic_o = 0x6CF;
-static constexpr uint32_t XK_Cyrillic_pe = 0x6D0;
-static constexpr uint32_t XK_Cyrillic_ya = 0x6D1;
-static constexpr uint32_t XK_Cyrillic_er = 0x6D2;
-static constexpr uint32_t XK_Cyrillic_es = 0x6D3;
-static constexpr uint32_t XK_Cyrillic_te = 0x6D4;
-static constexpr uint32_t XK_Cyrillic_u = 0x6D5;
-static constexpr uint32_t XK_Cyrillic_zhe = 0x6D6;
-static constexpr uint32_t XK_Cyrillic_ve = 0x6D7;
-static constexpr uint32_t XK_Cyrillic_softsign = 0x6D8;
-static constexpr uint32_t XK_Cyrillic_yeru = 0x6D9;
-static constexpr uint32_t XK_Cyrillic_ze = 0x6DA;
-static constexpr uint32_t XK_Cyrillic_sha = 0x6DB;
-static constexpr uint32_t XK_Cyrillic_e = 0x6DC;
-static constexpr uint32_t XK_Cyrillic_shcha = 0x6DD;
-static constexpr uint32_t XK_Cyrillic_che = 0x6DE;
-static constexpr uint32_t XK_Cyrillic_hardsign = 0x6DF;
-static constexpr uint32_t XK_Cyrillic_YU = 0x6E0;
-static constexpr uint32_t XK_Cyrillic_A = 0x6E1;
-static constexpr uint32_t XK_Cyrillic_BE = 0x6E2;
-static constexpr uint32_t XK_Cyrillic_TSE = 0x6E3;
-static constexpr uint32_t XK_Cyrillic_DE = 0x6E4;
-static constexpr uint32_t XK_Cyrillic_IE = 0x6E5;
-static constexpr uint32_t XK_Cyrillic_EF = 0x6E6;
-static constexpr uint32_t XK_Cyrillic_GHE = 0x6E7;
-static constexpr uint32_t XK_Cyrillic_HA = 0x6E8;
-static constexpr uint32_t XK_Cyrillic_I = 0x6E9;
-static constexpr uint32_t XK_Cyrillic_SHORTI = 0x6EA;
-static constexpr uint32_t XK_Cyrillic_KA = 0x6EB;
-static constexpr uint32_t XK_Cyrillic_EL = 0x6EC;
-static constexpr uint32_t XK_Cyrillic_EM = 0x6ED;
-static constexpr uint32_t XK_Cyrillic_EN = 0x6EE;
-static constexpr uint32_t XK_Cyrillic_O = 0x6EF;
-static constexpr uint32_t XK_Cyrillic_PE = 0x6F0;
-static constexpr uint32_t XK_Cyrillic_YA = 0x6F1;
-static constexpr uint32_t XK_Cyrillic_ER = 0x6F2;
-static constexpr uint32_t XK_Cyrillic_ES = 0x6F3;
-static constexpr uint32_t XK_Cyrillic_TE = 0x6F4;
-static constexpr uint32_t XK_Cyrillic_U = 0x6F5;
-static constexpr uint32_t XK_Cyrillic_ZHE = 0x6F6;
-static constexpr uint32_t XK_Cyrillic_VE = 0x6F7;
-static constexpr uint32_t XK_Cyrillic_SOFTSIGN = 0x6F8;
-static constexpr uint32_t XK_Cyrillic_YERU = 0x6F9;
-static constexpr uint32_t XK_Cyrillic_ZE = 0x6FA;
-static constexpr uint32_t XK_Cyrillic_SHA = 0x6FB;
-static constexpr uint32_t XK_Cyrillic_E = 0x6FC;
-static constexpr uint32_t XK_Cyrillic_SHCHA = 0x6FD;
-static constexpr uint32_t XK_Cyrillic_CHE = 0x6FE;
-static constexpr uint32_t XK_Cyrillic_HARDSIGN = 0x6FF;
-static constexpr uint32_t XK_Greek_ALPHAaccent = 0x7A1;
-static constexpr uint32_t XK_Greek_EPSILONaccent = 0x7A2;
-static constexpr uint32_t XK_Greek_ETAaccent = 0x7A3;
-static constexpr uint32_t XK_Greek_IOTAaccent = 0x7A4;
-static constexpr uint32_t XK_Greek_IOTAdiaeresis = 0x7A5;
-static constexpr uint32_t XK_Greek_IOTAdieresis = 0x7A5;
-static constexpr uint32_t XK_Greek_OMICRONaccent = 0x7A7;
-static constexpr uint32_t XK_Greek_UPSILONaccent = 0x7A8;
-static constexpr uint32_t XK_Greek_UPSILONdieresis = 0x7A9;
-static constexpr uint32_t XK_Greek_OMEGAaccent = 0x7AB;
-static constexpr uint32_t XK_Greek_accentdieresis = 0x7AE;
-static constexpr uint32_t XK_Greek_horizbar = 0x7AF;
-static constexpr uint32_t XK_Greek_alphaaccent = 0x7B1;
-static constexpr uint32_t XK_Greek_epsilonaccent = 0x7B2;
-static constexpr uint32_t XK_Greek_etaaccent = 0x7B3;
-static constexpr uint32_t XK_Greek_iotaaccent = 0x7B4;
-static constexpr uint32_t XK_Greek_iotadieresis = 0x7B5;
-static constexpr uint32_t XK_Greek_iotaaccentdieresis = 0x7B6;
-static constexpr uint32_t XK_Greek_omicronaccent = 0x7B7;
-static constexpr uint32_t XK_Greek_upsilonaccent = 0x7B8;
-static constexpr uint32_t XK_Greek_upsilondieresis = 0x7B9;
-static constexpr uint32_t XK_Greek_upsilonaccentdieresis = 0x7BA;
-static constexpr uint32_t XK_Greek_omegaaccent = 0x7BB;
-static constexpr uint32_t XK_Greek_ALPHA = 0x7C1;
-static constexpr uint32_t XK_Greek_BETA = 0x7C2;
-static constexpr uint32_t XK_Greek_GAMMA = 0x7C3;
-static constexpr uint32_t XK_Greek_DELTA = 0x7C4;
-static constexpr uint32_t XK_Greek_EPSILON = 0x7C5;
-static constexpr uint32_t XK_Greek_ZETA = 0x7C6;
-static constexpr uint32_t XK_Greek_ETA = 0x7C7;
-static constexpr uint32_t XK_Greek_THETA = 0x7C8;
-static constexpr uint32_t XK_Greek_IOTA = 0x7C9;
-static constexpr uint32_t XK_Greek_KAPPA = 0x7CA;
-static constexpr uint32_t XK_Greek_LAMBDA = 0x7CB;
-static constexpr uint32_t XK_Greek_LAMDA = 0x7CB;
-static constexpr uint32_t XK_Greek_MU = 0x7CC;
-static constexpr uint32_t XK_Greek_NU = 0x7CD;
-static constexpr uint32_t XK_Greek_XI = 0x7CE;
-static constexpr uint32_t XK_Greek_OMICRON = 0x7CF;
-static constexpr uint32_t XK_Greek_PI = 0x7D0;
-static constexpr uint32_t XK_Greek_RHO = 0x7D1;
-static constexpr uint32_t XK_Greek_SIGMA = 0x7D2;
-static constexpr uint32_t XK_Greek_TAU = 0x7D4;
-static constexpr uint32_t XK_Greek_UPSILON = 0x7D5;
-static constexpr uint32_t XK_Greek_PHI = 0x7D6;
-static constexpr uint32_t XK_Greek_CHI = 0x7D7;
-static constexpr uint32_t XK_Greek_PSI = 0x7D8;
-static constexpr uint32_t XK_Greek_OMEGA = 0x7D9;
-static constexpr uint32_t XK_Greek_alpha = 0x7E1;
-static constexpr uint32_t XK_Greek_beta = 0x7E2;
-static constexpr uint32_t XK_Greek_gamma = 0x7E3;
-static constexpr uint32_t XK_Greek_delta = 0x7E4;
-static constexpr uint32_t XK_Greek_epsilon = 0x7E5;
-static constexpr uint32_t XK_Greek_zeta = 0x7E6;
-static constexpr uint32_t XK_Greek_eta = 0x7E7;
-static constexpr uint32_t XK_Greek_theta = 0x7E8;
-static constexpr uint32_t XK_Greek_iota = 0x7E9;
-static constexpr uint32_t XK_Greek_kappa = 0x7EA;
-static constexpr uint32_t XK_Greek_lambda = 0x7EB;
-static constexpr uint32_t XK_Greek_lamda = 0x7EB;
-static constexpr uint32_t XK_Greek_mu = 0x7EC;
-static constexpr uint32_t XK_Greek_nu = 0x7ED;
-static constexpr uint32_t XK_Greek_xi = 0x7EE;
-static constexpr uint32_t XK_Greek_omicron = 0x7EF;
-static constexpr uint32_t XK_Greek_pi = 0x7F0;
-static constexpr uint32_t XK_Greek_rho = 0x7F1;
-static constexpr uint32_t XK_Greek_sigma = 0x7F2;
-static constexpr uint32_t XK_Greek_finalsmallsigma = 0x7F3;
-static constexpr uint32_t XK_Greek_tau = 0x7F4;
-static constexpr uint32_t XK_Greek_upsilon = 0x7F5;
-static constexpr uint32_t XK_Greek_phi = 0x7F6;
-static constexpr uint32_t XK_Greek_chi = 0x7F7;
-static constexpr uint32_t XK_Greek_psi = 0x7F8;
-static constexpr uint32_t XK_Greek_omega = 0x7F9;
-static constexpr uint32_t XK_leftradical = 0x8A1;
-static constexpr uint32_t XK_topleftradical = 0x8A2;
-static constexpr uint32_t XK_horizconnector = 0x8A3;
-static constexpr uint32_t XK_topintegral = 0x8A4;
-static constexpr uint32_t XK_botintegral = 0x8A5;
-static constexpr uint32_t XK_vertconnector = 0x8A6;
-static constexpr uint32_t XK_topleftsqbracket = 0x8A7;
-static constexpr uint32_t XK_botleftsqbracket = 0x8A8;
-static constexpr uint32_t XK_toprightsqbracket = 0x8A9;
-static constexpr uint32_t XK_botrightsqbracket = 0x8AA;
-static constexpr uint32_t XK_topleftparens = 0x8AB;
-static constexpr uint32_t XK_botleftparens = 0x8AC;
-static constexpr uint32_t XK_toprightparens = 0x8AD;
-static constexpr uint32_t XK_botrightparens = 0x8AE;
-static constexpr uint32_t XK_leftmiddlecurlybrace = 0x8AF;
-static constexpr uint32_t XK_rightmiddlecurlybrace = 0x8B0;
-static constexpr uint32_t XK_lessthanequal = 0x8BC;
-static constexpr uint32_t XK_notequal = 0x8BD;
-static constexpr uint32_t XK_greaterthanequal = 0x8BE;
-static constexpr uint32_t XK_integral = 0x8BF;
-static constexpr uint32_t XK_therefore = 0x8C0;
-static constexpr uint32_t XK_variation = 0x8C1;
-static constexpr uint32_t XK_infinity = 0x8C2;
-static constexpr uint32_t XK_nabla = 0x8C5;
-static constexpr uint32_t XK_approximate = 0x8C8;
-static constexpr uint32_t XK_similarequal = 0x8C9;
-static constexpr uint32_t XK_ifonlyif = 0x8CD;
-static constexpr uint32_t XK_implies = 0x8CE;
-static constexpr uint32_t XK_identical = 0x8CF;
-static constexpr uint32_t XK_radical = 0x8D6;
-static constexpr uint32_t XK_includedin = 0x8DA;
-static constexpr uint32_t XK_includes = 0x8DB;
-static constexpr uint32_t XK_intersection = 0x8DC;
-static constexpr uint32_t XK_union = 0x8DD;
-static constexpr uint32_t XK_logicaland = 0x8DE;
-static constexpr uint32_t XK_logicalor = 0x8DF;
-static constexpr uint32_t XK_partialderivative = 0x8EF;
-static constexpr uint32_t XK_function = 0x8F6;
-static constexpr uint32_t XK_leftarrow = 0x8FB;
-static constexpr uint32_t XK_uparrow = 0x8FC;
-static constexpr uint32_t XK_rightarrow = 0x8FD;
-static constexpr uint32_t XK_downarrow = 0x8FE;
-static constexpr uint32_t XK_soliddiamond = 0x9E0;
-static constexpr uint32_t XK_checkerboard = 0x9E1;
-static constexpr uint32_t XK_ht = 0x9E2;
-static constexpr uint32_t XK_ff = 0x9E3;
-static constexpr uint32_t XK_cr = 0x9E4;
-static constexpr uint32_t XK_lf = 0x9E5;
-static constexpr uint32_t XK_nl = 0x9E8;
-static constexpr uint32_t XK_vt = 0x9E9;
-static constexpr uint32_t XK_lowrightcorner = 0x9EA;
-static constexpr uint32_t XK_uprightcorner = 0x9EB;
-static constexpr uint32_t XK_upleftcorner = 0x9EC;
-static constexpr uint32_t XK_lowleftcorner = 0x9ED;
-static constexpr uint32_t XK_crossinglines = 0x9EE;
-static constexpr uint32_t XK_horizlinescan1 = 0x9EF;
-static constexpr uint32_t XK_horizlinescan3 = 0x9F0;
-static constexpr uint32_t XK_horizlinescan5 = 0x9F1;
-static constexpr uint32_t XK_horizlinescan7 = 0x9F2;
-static constexpr uint32_t XK_horizlinescan9 = 0x9F3;
-static constexpr uint32_t XK_leftt = 0x9F4;
-static constexpr uint32_t XK_rightt = 0x9F5;
-static constexpr uint32_t XK_bott = 0x9F6;
-static constexpr uint32_t XK_topt = 0x9F7;
-static constexpr uint32_t XK_vertbar = 0x9F8;
-static constexpr uint32_t XK_emspace = 0xAA1;
-static constexpr uint32_t XK_enspace = 0xAA2;
-static constexpr uint32_t XK_em3space = 0xAA3;
-static constexpr uint32_t XK_em4space = 0xAA4;
-static constexpr uint32_t XK_digitspace = 0xAA5;
-static constexpr uint32_t XK_punctspace = 0xAA6;
-static constexpr uint32_t XK_thinspace = 0xAA7;
-static constexpr uint32_t XK_hairspace = 0xAA8;
-static constexpr uint32_t XK_emdash = 0xAA9;
-static constexpr uint32_t XK_endash = 0xAAA;
-static constexpr uint32_t XK_signifblank = 0xAAC;
-static constexpr uint32_t XK_ellipsis = 0xAAE;
-static constexpr uint32_t XK_doubbaselinedot = 0xAAF;
-static constexpr uint32_t XK_onethird = 0xAB0;
-static constexpr uint32_t XK_twothirds = 0xAB1;
-static constexpr uint32_t XK_onefifth = 0xAB2;
-static constexpr uint32_t XK_twofifths = 0xAB3;
-static constexpr uint32_t XK_threefifths = 0xAB4;
-static constexpr uint32_t XK_fourfifths = 0xAB5;
-static constexpr uint32_t XK_onesixth = 0xAB6;
-static constexpr uint32_t XK_fivesixths = 0xAB7;
-static constexpr uint32_t XK_careof = 0xAB8;
-static constexpr uint32_t XK_figdash = 0xABB;
-static constexpr uint32_t XK_leftanglebracket = 0xABC;
-static constexpr uint32_t XK_decimalpoint = 0xABD;
-static constexpr uint32_t XK_rightanglebracket = 0xABE;
-static constexpr uint32_t XK_oneeighth = 0xAC3;
-static constexpr uint32_t XK_threeeighths = 0xAC4;
-static constexpr uint32_t XK_fiveeighths = 0xAC5;
-static constexpr uint32_t XK_seveneighths = 0xAC6;
-static constexpr uint32_t XK_trademark = 0xAC9;
-static constexpr uint32_t XK_signaturemark = 0xACA;
-static constexpr uint32_t XK_leftopentriangle = 0xACC;
-static constexpr uint32_t XK_rightopentriangle = 0xACD;
-static constexpr uint32_t XK_emopencircle = 0xACE;
-static constexpr uint32_t XK_emopenrectangle = 0xACF;
-static constexpr uint32_t XK_leftsinglequotemark = 0xAD0;
-static constexpr uint32_t XK_rightsinglequotemark = 0xAD1;
-static constexpr uint32_t XK_leftdoublequotemark = 0xAD2;
-static constexpr uint32_t XK_rightdoublequotemark = 0xAD3;
-static constexpr uint32_t XK_prescription = 0xAD4;
-static constexpr uint32_t XK_minutes = 0xAD6;
-static constexpr uint32_t XK_seconds = 0xAD7;
-static constexpr uint32_t XK_latincross = 0xAD9;
-static constexpr uint32_t XK_filledrectbullet = 0xADB;
-static constexpr uint32_t XK_filledlefttribullet = 0xADC;
-static constexpr uint32_t XK_filledrighttribullet = 0xADD;
-static constexpr uint32_t XK_emfilledcircle = 0xADE;
-static constexpr uint32_t XK_emfilledrect = 0xADF;
-static constexpr uint32_t XK_enopencircbullet = 0xAE0;
-static constexpr uint32_t XK_enopensquarebullet = 0xAE1;
-static constexpr uint32_t XK_openrectbullet = 0xAE2;
-static constexpr uint32_t XK_opentribulletup = 0xAE3;
-static constexpr uint32_t XK_opentribulletdown = 0xAE4;
-static constexpr uint32_t XK_openstar = 0xAE5;
-static constexpr uint32_t XK_enfilledcircbullet = 0xAE6;
-static constexpr uint32_t XK_enfilledsqbullet = 0xAE7;
-static constexpr uint32_t XK_filledtribulletup = 0xAE8;
-static constexpr uint32_t XK_filledtribulletdown = 0xAE9;
-static constexpr uint32_t XK_leftpointer = 0xAEA;
-static constexpr uint32_t XK_rightpointer = 0xAEB;
-static constexpr uint32_t XK_club = 0xAEC;
-static constexpr uint32_t XK_diamond = 0xAED;
-static constexpr uint32_t XK_heart = 0xAEE;
-static constexpr uint32_t XK_maltesecross = 0xAF0;
-static constexpr uint32_t XK_dagger = 0xAF1;
-static constexpr uint32_t XK_doubledagger = 0xAF2;
-static constexpr uint32_t XK_checkmark = 0xAF3;
-static constexpr uint32_t XK_ballotcross = 0xAF4;
-static constexpr uint32_t XK_musicalsharp = 0xAF5;
-static constexpr uint32_t XK_musicalflat = 0xAF6;
-static constexpr uint32_t XK_malesymbol = 0xAF7;
-static constexpr uint32_t XK_femalesymbol = 0xAF8;
-static constexpr uint32_t XK_telephone = 0xAF9;
-static constexpr uint32_t XK_telephonerecorder = 0xAFA;
-static constexpr uint32_t XK_phonographcopyright = 0xAFB;
-static constexpr uint32_t XK_caret = 0xAFC;
-static constexpr uint32_t XK_singlelowquotemark = 0xAFD;
-static constexpr uint32_t XK_doublelowquotemark = 0xAFE;
-static constexpr uint32_t XK_leftcaret = 0xBA3;
-static constexpr uint32_t XK_rightcaret = 0xBA6;
-static constexpr uint32_t XK_downcaret = 0xBA8;
-static constexpr uint32_t XK_upcaret = 0xBA9;
-static constexpr uint32_t XK_overbar = 0xBC0;
-static constexpr uint32_t XK_downtack = 0xBC2;
-static constexpr uint32_t XK_upshoe = 0xBC3;
-static constexpr uint32_t XK_downstile = 0xBC4;
-static constexpr uint32_t XK_underbar = 0xBC6;
-static constexpr uint32_t XK_jot = 0xBCA;
-static constexpr uint32_t XK_quad = 0xBCC;
-static constexpr uint32_t XK_uptack = 0xBCE;
-static constexpr uint32_t XK_circle = 0xBCF;
-static constexpr uint32_t XK_upstile = 0xBD3;
-static constexpr uint32_t XK_downshoe = 0xBD6;
-static constexpr uint32_t XK_rightshoe = 0xBD8;
-static constexpr uint32_t XK_leftshoe = 0xBDA;
-static constexpr uint32_t XK_lefttack = 0xBDC;
-static constexpr uint32_t XK_righttack = 0xBFC;
-static constexpr uint32_t XK_hebrew_doublelowline = 0xCDF;
-static constexpr uint32_t XK_hebrew_aleph = 0xCE0;
-static constexpr uint32_t XK_hebrew_bet = 0xCE1;
-static constexpr uint32_t XK_hebrew_gimel = 0xCE2;
-static constexpr uint32_t XK_hebrew_dalet = 0xCE3;
-static constexpr uint32_t XK_hebrew_he = 0xCE4;
-static constexpr uint32_t XK_hebrew_waw = 0xCE5;
-static constexpr uint32_t XK_hebrew_zain = 0xCE6;
-static constexpr uint32_t XK_hebrew_chet = 0xCE7;
-static constexpr uint32_t XK_hebrew_tet = 0xCE8;
-static constexpr uint32_t XK_hebrew_yod = 0xCE9;
-static constexpr uint32_t XK_hebrew_finalkaph = 0xCEA;
-static constexpr uint32_t XK_hebrew_kaph = 0xCEB;
-static constexpr uint32_t XK_hebrew_lamed = 0xCEC;
-static constexpr uint32_t XK_hebrew_finalmem = 0xCED;
-static constexpr uint32_t XK_hebrew_mem = 0xCEE;
-static constexpr uint32_t XK_hebrew_finalnun = 0xCEF;
-static constexpr uint32_t XK_hebrew_nun = 0xCF0;
-static constexpr uint32_t XK_hebrew_samech = 0xCF1;
-static constexpr uint32_t XK_hebrew_ayin = 0xCF2;
-static constexpr uint32_t XK_hebrew_finalpe = 0xCF3;
-static constexpr uint32_t XK_hebrew_pe = 0xCF4;
-static constexpr uint32_t XK_hebrew_finalzade = 0xCF5;
-static constexpr uint32_t XK_hebrew_zade = 0xCF6;
-static constexpr uint32_t XK_hebrew_qoph = 0xCF7;
-static constexpr uint32_t XK_hebrew_resh = 0xCF8;
-static constexpr uint32_t XK_hebrew_shin = 0xCF9;
-static constexpr uint32_t XK_hebrew_taw = 0xCFA;
-static constexpr uint32_t XK_Thai_kokai = 0xDA1;
-static constexpr uint32_t XK_Thai_khokhai = 0xDA2;
-static constexpr uint32_t XK_Thai_khokhuat = 0xDA3;
-static constexpr uint32_t XK_Thai_khokhwai = 0xDA4;
-static constexpr uint32_t XK_Thai_khokhon = 0xDA5;
-static constexpr uint32_t XK_Thai_khorakhang = 0xDA6;
-static constexpr uint32_t XK_Thai_ngongu = 0xDA7;
-static constexpr uint32_t XK_Thai_chochan = 0xDA8;
-static constexpr uint32_t XK_Thai_choching = 0xDA9;
-static constexpr uint32_t XK_Thai_chochang = 0xDAA;
-static constexpr uint32_t XK_Thai_soso = 0xDAB;
-static constexpr uint32_t XK_Thai_chochoe = 0xDAC;
-static constexpr uint32_t XK_Thai_yoying = 0xDAD;
-static constexpr uint32_t XK_Thai_dochada = 0xDAE;
-static constexpr uint32_t XK_Thai_topatak = 0xDAF;
-static constexpr uint32_t XK_Thai_thothan = 0xDB0;
-static constexpr uint32_t XK_Thai_thonangmontho = 0xDB1;
-static constexpr uint32_t XK_Thai_thophuthao = 0xDB2;
-static constexpr uint32_t XK_Thai_nonen = 0xDB3;
-static constexpr uint32_t XK_Thai_dodek = 0xDB4;
-static constexpr uint32_t XK_Thai_totao = 0xDB5;
-static constexpr uint32_t XK_Thai_thothung = 0xDB6;
-static constexpr uint32_t XK_Thai_thothahan = 0xDB7;
-static constexpr uint32_t XK_Thai_thothong = 0xDB8;
-static constexpr uint32_t XK_Thai_nonu = 0xDB9;
-static constexpr uint32_t XK_Thai_bobaimai = 0xDBA;
-static constexpr uint32_t XK_Thai_popla = 0xDBB;
-static constexpr uint32_t XK_Thai_phophung = 0xDBC;
-static constexpr uint32_t XK_Thai_fofa = 0xDBD;
-static constexpr uint32_t XK_Thai_phophan = 0xDBE;
-static constexpr uint32_t XK_Thai_fofan = 0xDBF;
-static constexpr uint32_t XK_Thai_phosamphao = 0xDC0;
-static constexpr uint32_t XK_Thai_moma = 0xDC1;
-static constexpr uint32_t XK_Thai_yoyak = 0xDC2;
-static constexpr uint32_t XK_Thai_rorua = 0xDC3;
-static constexpr uint32_t XK_Thai_ru = 0xDC4;
-static constexpr uint32_t XK_Thai_loling = 0xDC5;
-static constexpr uint32_t XK_Thai_lu = 0xDC6;
-static constexpr uint32_t XK_Thai_wowaen = 0xDC7;
-static constexpr uint32_t XK_Thai_sosala = 0xDC8;
-static constexpr uint32_t XK_Thai_sorusi = 0xDC9;
-static constexpr uint32_t XK_Thai_sosua = 0xDCA;
-static constexpr uint32_t XK_Thai_hohip = 0xDCB;
-static constexpr uint32_t XK_Thai_lochula = 0xDCC;
-static constexpr uint32_t XK_Thai_oang = 0xDCD;
-static constexpr uint32_t XK_Thai_honokhuk = 0xDCE;
-static constexpr uint32_t XK_Thai_paiyannoi = 0xDCF;
-static constexpr uint32_t XK_Thai_saraa = 0xDD0;
-static constexpr uint32_t XK_Thai_maihanakat = 0xDD1;
-static constexpr uint32_t XK_Thai_saraaa = 0xDD2;
-static constexpr uint32_t XK_Thai_saraam = 0xDD3;
-static constexpr uint32_t XK_Thai_sarai = 0xDD4;
-static constexpr uint32_t XK_Thai_saraii = 0xDD5;
-static constexpr uint32_t XK_Thai_saraue = 0xDD6;
-static constexpr uint32_t XK_Thai_sarauee = 0xDD7;
-static constexpr uint32_t XK_Thai_sarau = 0xDD8;
-static constexpr uint32_t XK_Thai_sarauu = 0xDD9;
-static constexpr uint32_t XK_Thai_phinthu = 0xDDA;
-static constexpr uint32_t XK_Thai_baht = 0xDDF;
-static constexpr uint32_t XK_Thai_sarae = 0xDE0;
-static constexpr uint32_t XK_Thai_saraae = 0xDE1;
-static constexpr uint32_t XK_Thai_sarao = 0xDE2;
-static constexpr uint32_t XK_Thai_saraaimaimuan = 0xDE3;
-static constexpr uint32_t XK_Thai_saraaimaimalai = 0xDE4;
-static constexpr uint32_t XK_Thai_lakkhangyao = 0xDE5;
-static constexpr uint32_t XK_Thai_maiyamok = 0xDE6;
-static constexpr uint32_t XK_Thai_maitaikhu = 0xDE7;
-static constexpr uint32_t XK_Thai_maiek = 0xDE8;
-static constexpr uint32_t XK_Thai_maitho = 0xDE9;
-static constexpr uint32_t XK_Thai_maitri = 0xDEA;
-static constexpr uint32_t XK_Thai_maichattawa = 0xDEB;
-static constexpr uint32_t XK_Thai_thanthakhat = 0xDEC;
-static constexpr uint32_t XK_Thai_nikhahit = 0xDED;
-static constexpr uint32_t XK_Thai_leksun = 0xDF0;
-static constexpr uint32_t XK_Thai_leknung = 0xDF1;
-static constexpr uint32_t XK_Thai_leksong = 0xDF2;
-static constexpr uint32_t XK_Thai_leksam = 0xDF3;
-static constexpr uint32_t XK_Thai_leksi = 0xDF4;
-static constexpr uint32_t XK_Thai_lekha = 0xDF5;
-static constexpr uint32_t XK_Thai_lekhok = 0xDF6;
-static constexpr uint32_t XK_Thai_lekchet = 0xDF7;
-static constexpr uint32_t XK_Thai_lekpaet = 0xDF8;
-static constexpr uint32_t XK_Thai_lekkao = 0xDF9;
-static constexpr uint32_t XK_Hangul_Kiyeog = 0xEA1;
-static constexpr uint32_t XK_Hangul_SsangKiyeog = 0xEA2;
-static constexpr uint32_t XK_Hangul_KiyeogSios = 0xEA3;
-static constexpr uint32_t XK_Hangul_Nieun = 0xEA4;
-static constexpr uint32_t XK_Hangul_NieunJieuj = 0xEA5;
-static constexpr uint32_t XK_Hangul_NieunHieuh = 0xEA6;
-static constexpr uint32_t XK_Hangul_Dikeud = 0xEA7;
-static constexpr uint32_t XK_Hangul_SsangDikeud = 0xEA8;
-static constexpr uint32_t XK_Hangul_Rieul = 0xEA9;
-static constexpr uint32_t XK_Hangul_RieulKiyeog = 0xEAA;
-static constexpr uint32_t XK_Hangul_RieulMieum = 0xEAB;
-static constexpr uint32_t XK_Hangul_RieulPieub = 0xEAC;
-static constexpr uint32_t XK_Hangul_RieulSios = 0xEAD;
-static constexpr uint32_t XK_Hangul_RieulTieut = 0xEAE;
-static constexpr uint32_t XK_Hangul_RieulPhieuf = 0xEAF;
-static constexpr uint32_t XK_Hangul_RieulHieuh = 0xEB0;
-static constexpr uint32_t XK_Hangul_Mieum = 0xEB1;
-static constexpr uint32_t XK_Hangul_Pieub = 0xEB2;
-static constexpr uint32_t XK_Hangul_SsangPieub = 0xEB3;
-static constexpr uint32_t XK_Hangul_PieubSios = 0xEB4;
-static constexpr uint32_t XK_Hangul_Sios = 0xEB5;
-static constexpr uint32_t XK_Hangul_SsangSios = 0xEB6;
-static constexpr uint32_t XK_Hangul_Ieung = 0xEB7;
-static constexpr uint32_t XK_Hangul_Jieuj = 0xEB8;
-static constexpr uint32_t XK_Hangul_SsangJieuj = 0xEB9;
-static constexpr uint32_t XK_Hangul_Cieuc = 0xEBA;
-static constexpr uint32_t XK_Hangul_Khieuq = 0xEBB;
-static constexpr uint32_t XK_Hangul_Tieut = 0xEBC;
-static constexpr uint32_t XK_Hangul_Phieuf = 0xEBD;
-static constexpr uint32_t XK_Hangul_Hieuh = 0xEBE;
-static constexpr uint32_t XK_Hangul_A = 0xEBF;
-static constexpr uint32_t XK_Hangul_AE = 0xEC0;
-static constexpr uint32_t XK_Hangul_YA = 0xEC1;
-static constexpr uint32_t XK_Hangul_YAE = 0xEC2;
-static constexpr uint32_t XK_Hangul_EO = 0xEC3;
-static constexpr uint32_t XK_Hangul_E = 0xEC4;
-static constexpr uint32_t XK_Hangul_YEO = 0xEC5;
-static constexpr uint32_t XK_Hangul_YE = 0xEC6;
-static constexpr uint32_t XK_Hangul_O = 0xEC7;
-static constexpr uint32_t XK_Hangul_WA = 0xEC8;
-static constexpr uint32_t XK_Hangul_WAE = 0xEC9;
-static constexpr uint32_t XK_Hangul_OE = 0xECA;
-static constexpr uint32_t XK_Hangul_YO = 0xECB;
-static constexpr uint32_t XK_Hangul_U = 0xECC;
-static constexpr uint32_t XK_Hangul_WEO = 0xECD;
-static constexpr uint32_t XK_Hangul_WE = 0xECE;
-static constexpr uint32_t XK_Hangul_WI = 0xECF;
-static constexpr uint32_t XK_Hangul_YU = 0xED0;
-static constexpr uint32_t XK_Hangul_EU = 0xED1;
-static constexpr uint32_t XK_Hangul_YI = 0xED2;
-static constexpr uint32_t XK_Hangul_I = 0xED3;
-static constexpr uint32_t XK_Hangul_J_Kiyeog = 0xED4;
-static constexpr uint32_t XK_Hangul_J_SsangKiyeog = 0xED5;
-static constexpr uint32_t XK_Hangul_J_KiyeogSios = 0xED6;
-static constexpr uint32_t XK_Hangul_J_Nieun = 0xED7;
-static constexpr uint32_t XK_Hangul_J_NieunJieuj = 0xED8;
-static constexpr uint32_t XK_Hangul_J_NieunHieuh = 0xED9;
-static constexpr uint32_t XK_Hangul_J_Dikeud = 0xEDA;
-static constexpr uint32_t XK_Hangul_J_Rieul = 0xEDB;
-static constexpr uint32_t XK_Hangul_J_RieulKiyeog = 0xEDC;
-static constexpr uint32_t XK_Hangul_J_RieulMieum = 0xEDD;
-static constexpr uint32_t XK_Hangul_J_RieulPieub = 0xEDE;
-static constexpr uint32_t XK_Hangul_J_RieulSios = 0xEDF;
-static constexpr uint32_t XK_Hangul_J_RieulTieut = 0xEE0;
-static constexpr uint32_t XK_Hangul_J_RieulPhieuf = 0xEE1;
-static constexpr uint32_t XK_Hangul_J_RieulHieuh = 0xEE2;
-static constexpr uint32_t XK_Hangul_J_Mieum = 0xEE3;
-static constexpr uint32_t XK_Hangul_J_Pieub = 0xEE4;
-static constexpr uint32_t XK_Hangul_J_PieubSios = 0xEE5;
-static constexpr uint32_t XK_Hangul_J_Sios = 0xEE6;
-static constexpr uint32_t XK_Hangul_J_SsangSios = 0xEE7;
-static constexpr uint32_t XK_Hangul_J_Ieung = 0xEE8;
-static constexpr uint32_t XK_Hangul_J_Jieuj = 0xEE9;
-static constexpr uint32_t XK_Hangul_J_Cieuc = 0xEEA;
-static constexpr uint32_t XK_Hangul_J_Khieuq = 0xEEB;
-static constexpr uint32_t XK_Hangul_J_Tieut = 0xEEC;
-static constexpr uint32_t XK_Hangul_J_Phieuf = 0xEED;
-static constexpr uint32_t XK_Hangul_J_Hieuh = 0xEEE;
-static constexpr uint32_t XK_Hangul_RieulYeorinHieuh = 0xEEF;
-static constexpr uint32_t XK_Hangul_SunkyeongeumMieum = 0xEF0;
-static constexpr uint32_t XK_Hangul_SunkyeongeumPieub = 0xEF1;
-static constexpr uint32_t XK_Hangul_PanSios = 0xEF2;
-static constexpr uint32_t XK_Hangul_KkogjiDalrinIeung = 0xEF3;
-static constexpr uint32_t XK_Hangul_SunkyeongeumPhieuf = 0xEF4;
-static constexpr uint32_t XK_Hangul_YeorinHieuh = 0xEF5;
-static constexpr uint32_t XK_Hangul_AraeA = 0xEF6;
-static constexpr uint32_t XK_Hangul_AraeAE = 0xEF7;
-static constexpr uint32_t XK_Hangul_J_PanSios = 0xEF8;
-static constexpr uint32_t XK_Hangul_J_KkogjiDalrinIeung = 0xEF9;
-static constexpr uint32_t XK_Hangul_J_YeorinHieuh = 0xEFA;
-static constexpr uint32_t XK_Korean_Won = 0xEFF;
-static constexpr uint32_t XK_OE = 0x13BC;
-static constexpr uint32_t XK_oe = 0x13BD;
-static constexpr uint32_t XK_Ydiaeresis = 0x13BE;
-static constexpr uint32_t XK_EuroSign = 0x20AC;
-static constexpr uint32_t XK_3270_Duplicate = 0xFD01;
-static constexpr uint32_t XK_3270_FieldMark = 0xFD02;
-static constexpr uint32_t XK_3270_Right2 = 0xFD03;
-static constexpr uint32_t XK_3270_Left2 = 0xFD04;
-static constexpr uint32_t XK_3270_BackTab = 0xFD05;
-static constexpr uint32_t XK_3270_EraseEOF = 0xFD06;
-static constexpr uint32_t XK_3270_EraseInput = 0xFD07;
-static constexpr uint32_t XK_3270_Reset = 0xFD08;
-static constexpr uint32_t XK_3270_Quit = 0xFD09;
-static constexpr uint32_t XK_3270_PA1 = 0xFD0A;
-static constexpr uint32_t XK_3270_PA2 = 0xFD0B;
-static constexpr uint32_t XK_3270_PA3 = 0xFD0C;
-static constexpr uint32_t XK_3270_Test = 0xFD0D;
-static constexpr uint32_t XK_3270_Attn = 0xFD0E;
-static constexpr uint32_t XK_3270_CursorBlink = 0xFD0F;
-static constexpr uint32_t XK_3270_AltCursor = 0xFD10;
-static constexpr uint32_t XK_3270_KeyClick = 0xFD11;
-static constexpr uint32_t XK_3270_Jump = 0xFD12;
-static constexpr uint32_t XK_3270_Ident = 0xFD13;
-static constexpr uint32_t XK_3270_Rule = 0xFD14;
-static constexpr uint32_t XK_3270_Copy = 0xFD15;
-static constexpr uint32_t XK_3270_Play = 0xFD16;
-static constexpr uint32_t XK_3270_Setup = 0xFD17;
-static constexpr uint32_t XK_3270_Record = 0xFD18;
-static constexpr uint32_t XK_3270_ChangeScreen = 0xFD19;
-static constexpr uint32_t XK_3270_DeleteWord = 0xFD1A;
-static constexpr uint32_t XK_3270_ExSelect = 0xFD1B;
-static constexpr uint32_t XK_3270_CursorSelect = 0xFD1C;
-static constexpr uint32_t XK_3270_PrintScreen = 0xFD1D;
-static constexpr uint32_t XK_3270_Enter = 0xFD1E;
-static constexpr uint32_t XK_ISO_Lock = 0xFE01;
-static constexpr uint32_t XK_ISO_Level3_Shift = 0xFE03;
-static constexpr uint32_t XK_ISO_Level3_Latch = 0xFE04;
-static constexpr uint32_t XK_ISO_Next_Group = 0xFE08;
-static constexpr uint32_t XK_ISO_Next_Group_Lock = 0xFE09;
-static constexpr uint32_t XK_ISO_Prev_Group = 0xFE0A;
-static constexpr uint32_t XK_ISO_Prev_Group_Lock = 0xFE0B;
-static constexpr uint32_t XK_ISO_First_Group = 0xFE0C;
-static constexpr uint32_t XK_ISO_First_Group_Lock = 0xFE0D;
-static constexpr uint32_t XK_ISO_Last_Group = 0xFE0E;
-static constexpr uint32_t XK_ISO_Last_Group_Lock = 0xFE0F;
-static constexpr uint32_t XK_ISO_Level5_Shift = 0xFE11;
-static constexpr uint32_t XK_ISO_Level5_Lock = 0xFE13;
-static constexpr uint32_t XK_ISO_Left_Tab = 0xFE20;
-static constexpr uint32_t XK_ISO_Enter = 0xFE34;
-static constexpr uint32_t XK_dead_grave = 0xFE50;
-static constexpr uint32_t XK_dead_acute = 0xFE51;
-static constexpr uint32_t XK_dead_circumflex = 0xFE52;
-static constexpr uint32_t XK_dead_tilde = 0xFE53;
-static constexpr uint32_t XK_dead_macron = 0xFE54;
-static constexpr uint32_t XK_dead_breve = 0xFE55;
-static constexpr uint32_t XK_dead_abovedot = 0xFE56;
-static constexpr uint32_t XK_dead_diaeresis = 0xFE57;
-static constexpr uint32_t XK_dead_abovering = 0xFE58;
-static constexpr uint32_t XK_dead_doubleacute = 0xFE59;
-static constexpr uint32_t XK_dead_caron = 0xFE5A;
-static constexpr uint32_t XK_dead_cedilla = 0xFE5B;
-static constexpr uint32_t XK_dead_ogonek = 0xFE5C;
-static constexpr uint32_t XK_dead_iota = 0xFE5D;
-static constexpr uint32_t XK_dead_voiced_sound = 0xFE5E;
-static constexpr uint32_t XK_dead_semivoiced_sound = 0xFE5F;
-static constexpr uint32_t XK_dead_belowdot = 0xFE60;
-static constexpr uint32_t XK_dead_hook = 0xFE61;
-static constexpr uint32_t XK_dead_horn = 0xFE62;
-static constexpr uint32_t XK_dead_stroke = 0xFE63;
-static constexpr uint32_t XK_dead_abovecomma = 0xFE64;
-static constexpr uint32_t XK_dead_abovereversedcomma = 0xFE65;
-static constexpr uint32_t XK_dead_doublegrave = 0xFE66;
-static constexpr uint32_t XK_dead_belowring = 0xFE67;
-static constexpr uint32_t XK_dead_belowmacron = 0xFE68;
-static constexpr uint32_t XK_dead_belowcircumflex = 0xFE69;
-static constexpr uint32_t XK_dead_belowtilde = 0xFE6A;
-static constexpr uint32_t XK_dead_belowbreve = 0xFE6B;
-static constexpr uint32_t XK_dead_belowdiaeresis = 0xFE6C;
-static constexpr uint32_t XK_dead_invertedbreve = 0xFE6D;
-static constexpr uint32_t XK_dead_belowcomma = 0xFE6E;
-static constexpr uint32_t XK_dead_currency = 0xFE6F;
-static constexpr uint32_t XK_dead_greek = 0xFE8C;
-static constexpr uint32_t XK_Next_Virtual_Screen = 0xFED2;
-static constexpr uint32_t XK_BackSpace = 0xFF08;
-static constexpr uint32_t XK_Tab = 0xFF09;
-static constexpr uint32_t XK_Linefeed = 0xFF0A;
-static constexpr uint32_t XK_Clear = 0xFF0B;
-static constexpr uint32_t XK_Return = 0xFF0D;
-static constexpr uint32_t XK_Pause = 0xFF13;
-static constexpr uint32_t XK_Scroll_Lock = 0xFF14;
-static constexpr uint32_t XK_Sys_Req = 0xFF15;
-static constexpr uint32_t XK_Escape = 0xFF1B;
-static constexpr uint32_t XK_Multi_key = 0xFF20;
-static constexpr uint32_t XK_Kanji = 0xFF21;
-static constexpr uint32_t XK_Muhenkan = 0xFF22;
-static constexpr uint32_t XK_Henkan = 0xFF23;
-static constexpr uint32_t XK_Henkan_Mode = 0xFF23;
-static constexpr uint32_t XK_Romaji = 0xFF24;
-static constexpr uint32_t XK_Hiragana = 0xFF25;
-static constexpr uint32_t XK_Katakana = 0xFF26;
-static constexpr uint32_t XK_Hiragana_Katakana = 0xFF27;
-static constexpr uint32_t XK_Zenkaku = 0xFF28;
-static constexpr uint32_t XK_Hankaku = 0xFF29;
-static constexpr uint32_t XK_Zenkaku_Hankaku = 0xFF2A;
-static constexpr uint32_t XK_Kana_Lock = 0xFF2D;
-static constexpr uint32_t XK_Kana_Shift = 0xFF2E;
-static constexpr uint32_t XK_Eisu_Shift = 0xFF2F;
-static constexpr uint32_t XK_Eisu_toggle = 0xFF30;
-static constexpr uint32_t XK_Hangul = 0xFF31;
-static constexpr uint32_t XK_Hangul_Start = 0xFF32;
-static constexpr uint32_t XK_Hangul_End = 0xFF33;
-static constexpr uint32_t XK_Hangul_Hanja = 0xFF34;
-static constexpr uint32_t XK_Hangul_Jamo = 0xFF35;
-static constexpr uint32_t XK_Hangul_Romaja = 0xFF36;
-static constexpr uint32_t XK_Codeinput = 0xFF37;
-static constexpr uint32_t XK_Hangul_Jeonja = 0xFF38;
-static constexpr uint32_t XK_Hangul_Banja = 0xFF39;
-static constexpr uint32_t XK_Hangul_PreHanja = 0xFF3A;
-static constexpr uint32_t XK_Hangul_PostHanja = 0xFF3B;
-static constexpr uint32_t XK_SingleCandidate = 0xFF3C;
-static constexpr uint32_t XK_MultipleCandidate = 0xFF3D;
-static constexpr uint32_t XK_PreviousCandidate = 0xFF3E;
-static constexpr uint32_t XK_Hangul_Special = 0xFF3F;
-static constexpr uint32_t XK_Home = 0xFF50;
-static constexpr uint32_t XK_Left = 0xFF51;
-static constexpr uint32_t XK_Up = 0xFF52;
-static constexpr uint32_t XK_Right = 0xFF53;
-static constexpr uint32_t XK_Down = 0xFF54;
-static constexpr uint32_t XK_Page_Up = 0xFF55;
-static constexpr uint32_t XK_Prior = 0xFF55;
-static constexpr uint32_t XK_Next = 0xFF56;
-static constexpr uint32_t XK_Page_Down = 0xFF56;
-static constexpr uint32_t XK_End = 0xFF57;
-static constexpr uint32_t XK_Select = 0xFF60;
-static constexpr uint32_t XK_Print = 0xFF61;
-static constexpr uint32_t XK_Execute = 0xFF62;
-static constexpr uint32_t XK_Insert = 0xFF63;
-static constexpr uint32_t XK_Undo = 0xFF65;
-static constexpr uint32_t XK_Redo = 0xFF66;
-static constexpr uint32_t XK_Menu = 0xFF67;
-static constexpr uint32_t XK_Find = 0xFF68;
-static constexpr uint32_t XK_Cancel = 0xFF69;
-static constexpr uint32_t XK_Help = 0xFF6A;
-static constexpr uint32_t XK_Break = 0xFF6B;
-static constexpr uint32_t XK_Mode_switch = 0xFF7E;
-static constexpr uint32_t XK_Num_Lock = 0xFF7F;
-static constexpr uint32_t XK_KP_Space = 0xFF80;
-static constexpr uint32_t XK_KP_Tab = 0xFF89;
-static constexpr uint32_t XK_KP_Enter = 0xFF8D;
-static constexpr uint32_t XK_KP_F1 = 0xFF91;
-static constexpr uint32_t XK_KP_F2 = 0xFF92;
-static constexpr uint32_t XK_KP_F3 = 0xFF93;
-static constexpr uint32_t XK_KP_F4 = 0xFF94;
-static constexpr uint32_t XK_KP_Home = 0xFF95;
-static constexpr uint32_t XK_KP_Left = 0xFF96;
-static constexpr uint32_t XK_KP_Up = 0xFF97;
-static constexpr uint32_t XK_KP_Right = 0xFF98;
-static constexpr uint32_t XK_KP_Down = 0xFF99;
-static constexpr uint32_t XK_KP_Page_Up = 0xFF9A;
-static constexpr uint32_t XK_KP_Prior = 0xFF9A;
-static constexpr uint32_t XK_KP_Next = 0xFF9B;
-static constexpr uint32_t XK_KP_Page_Down = 0xFF9B;
-static constexpr uint32_t XK_KP_End = 0xFF9C;
-static constexpr uint32_t XK_KP_Begin = 0xFF9D;
-static constexpr uint32_t XK_KP_Insert = 0xFF9E;
-static constexpr uint32_t XK_KP_Delete = 0xFF9F;
-static constexpr uint32_t XK_KP_Multiply = 0xFFAA;
-static constexpr uint32_t XK_KP_Add = 0xFFAB;
-static constexpr uint32_t XK_KP_Separator = 0xFFAC;
-static constexpr uint32_t XK_KP_Subtract = 0xFFAD;
-static constexpr uint32_t XK_KP_Decimal = 0xFFAE;
-static constexpr uint32_t XK_KP_Divide = 0xFFAF;
-static constexpr uint32_t XK_KP_0 = 0xFFB0;
-static constexpr uint32_t XK_KP_1 = 0xFFB1;
-static constexpr uint32_t XK_KP_2 = 0xFFB2;
-static constexpr uint32_t XK_KP_3 = 0xFFB3;
-static constexpr uint32_t XK_KP_4 = 0xFFB4;
-static constexpr uint32_t XK_KP_5 = 0xFFB5;
-static constexpr uint32_t XK_KP_6 = 0xFFB6;
-static constexpr uint32_t XK_KP_7 = 0xFFB7;
-static constexpr uint32_t XK_KP_8 = 0xFFB8;
-static constexpr uint32_t XK_KP_9 = 0xFFB9;
-static constexpr uint32_t XK_KP_Equal = 0xFFBD;
-static constexpr uint32_t XK_F1 = 0xFFBE;
-static constexpr uint32_t XK_F2 = 0xFFBF;
-static constexpr uint32_t XK_F3 = 0xFFC0;
-static constexpr uint32_t XK_F4 = 0xFFC1;
-static constexpr uint32_t XK_F5 = 0xFFC2;
-static constexpr uint32_t XK_F6 = 0xFFC3;
-static constexpr uint32_t XK_F7 = 0xFFC4;
-static constexpr uint32_t XK_F8 = 0xFFC5;
-static constexpr uint32_t XK_F9 = 0xFFC6;
-static constexpr uint32_t XK_F10 = 0xFFC7;
-static constexpr uint32_t XK_F11 = 0xFFC8;
-static constexpr uint32_t XK_F12 = 0xFFC9;
-static constexpr uint32_t XK_F13 = 0xFFCA;
-static constexpr uint32_t XK_F14 = 0xFFCB;
-static constexpr uint32_t XK_F15 = 0xFFCC;
-static constexpr uint32_t XK_F16 = 0xFFCD;
-static constexpr uint32_t XK_F17 = 0xFFCE;
-static constexpr uint32_t XK_F18 = 0xFFCF;
-static constexpr uint32_t XK_F19 = 0xFFD0;
-static constexpr uint32_t XK_F20 = 0xFFD1;
-static constexpr uint32_t XK_F21 = 0xFFD2;
-static constexpr uint32_t XK_F22 = 0xFFD3;
-static constexpr uint32_t XK_F23 = 0xFFD4;
-static constexpr uint32_t XK_F24 = 0xFFD5;
-static constexpr uint32_t XK_F25 = 0xFFD6;
-static constexpr uint32_t XK_F26 = 0xFFD7;
-static constexpr uint32_t XK_F27 = 0xFFD8;
-static constexpr uint32_t XK_F28 = 0xFFD9;
-static constexpr uint32_t XK_F29 = 0xFFDA;
-static constexpr uint32_t XK_F30 = 0xFFDB;
-static constexpr uint32_t XK_F31 = 0xFFDC;
-static constexpr uint32_t XK_F32 = 0xFFDD;
-static constexpr uint32_t XK_F33 = 0xFFDE;
-static constexpr uint32_t XK_F34 = 0xFFDF;
-static constexpr uint32_t XK_F35 = 0xFFE0;
-static constexpr uint32_t XK_Shift_L = 0xFFE1;
-static constexpr uint32_t XK_Shift_R = 0xFFE2;
-static constexpr uint32_t XK_Control_L = 0xFFE3;
-static constexpr uint32_t XK_Control_R = 0xFFE4;
-static constexpr uint32_t XK_Caps_Lock = 0xFFE5;
-static constexpr uint32_t XK_Shift_Lock = 0xFFE6;
-static constexpr uint32_t XK_Meta_L = 0xFFE7;
-static constexpr uint32_t XK_Meta_R = 0xFFE8;
-static constexpr uint32_t XK_Alt_L = 0xFFE9;
-static constexpr uint32_t XK_Alt_R = 0xFFEA;
-static constexpr uint32_t XK_Super_L = 0xFFEB;
-static constexpr uint32_t XK_Super_R = 0xFFEC;
-static constexpr uint32_t XK_Hyper_L = 0xFFED;
-static constexpr uint32_t XK_Hyper_R = 0xFFEE;
-static constexpr uint32_t XK_Delete = 0xFFFF;
-static constexpr uint32_t XK_VoidSymbol = 0xFFFFFF;
-static constexpr uint32_t SunXK_Props = 0x1005FF70;
-static constexpr uint32_t SunXK_Copy = 0x1005FF72;
-static constexpr uint32_t SunXK_Open = 0x1005FF73;
-static constexpr uint32_t SunXK_Paste = 0x1005FF74;
-static constexpr uint32_t SunXK_Cut = 0x1005FF75;
-static constexpr uint32_t XF86XK_ClearGrab = 0x1008FE21;
-static constexpr uint32_t XF86XK_Next_VMode = 0x1008FE22;
-static constexpr uint32_t XF86XK_MonBrightnessUp = 0x1008FF02;
-static constexpr uint32_t XF86XK_MonBrightnessDown = 0x1008FF03;
-static constexpr uint32_t XF86XK_KbdBrightnessUp = 0x1008FF05;
-static constexpr uint32_t XF86XK_KbdBrightnessDown = 0x1008FF06;
-static constexpr uint32_t XF86XK_Standby = 0x1008FF10;
-static constexpr uint32_t XF86XK_AudioLowerVolume = 0x1008FF11;
-static constexpr uint32_t XF86XK_AudioMute = 0x1008FF12;
-static constexpr uint32_t XF86XK_AudioRaiseVolume = 0x1008FF13;
-static constexpr uint32_t XF86XK_AudioPlay = 0x1008FF14;
-static constexpr uint32_t XF86XK_AudioStop = 0x1008FF15;
-static constexpr uint32_t XF86XK_AudioPrev = 0x1008FF16;
-static constexpr uint32_t XF86XK_AudioNext = 0x1008FF17;
-static constexpr uint32_t XF86XK_HomePage = 0x1008FF18;
-static constexpr uint32_t XF86XK_Mail = 0x1008FF19;
-static constexpr uint32_t XF86XK_Search = 0x1008FF1B;
-static constexpr uint32_t XF86XK_AudioRecord = 0x1008FF1C;
-static constexpr uint32_t XF86XK_Calculator = 0x1008FF1D;
-static constexpr uint32_t XF86XK_Calendar = 0x1008FF20;
-static constexpr uint32_t XF86XK_Back = 0x1008FF26;
-static constexpr uint32_t XF86XK_Forward = 0x1008FF27;
-static constexpr uint32_t XF86XK_Stop = 0x1008FF28;
-static constexpr uint32_t XF86XK_Refresh = 0x1008FF29;
-static constexpr uint32_t XF86XK_PowerOff = 0x1008FF2A;
-static constexpr uint32_t XF86XK_WakeUp = 0x1008FF2B;
-static constexpr uint32_t XF86XK_Eject = 0x1008FF2C;
-static constexpr uint32_t XF86XK_ScreenSaver = 0x1008FF2D;
-static constexpr uint32_t XF86XK_WWW = 0x1008FF2E;
-static constexpr uint32_t XF86XK_Sleep = 0x1008FF2F;
-static constexpr uint32_t XF86XK_Favorites = 0x1008FF30;
-static constexpr uint32_t XF86XK_AudioPause = 0x1008FF31;
-static constexpr uint32_t XF86XK_AudioMedia = 0x1008FF32;
-static constexpr uint32_t XF86XK_MyComputer = 0x1008FF33;
-static constexpr uint32_t XF86XK_OpenURL = 0x1008FF38;
-static constexpr uint32_t XF86XK_AudioRewind = 0x1008FF3E;
-static constexpr uint32_t XF86XK_BackForward = 0x1008FF3F;
-static constexpr uint32_t XF86XK_Launch5 = 0x1008FF45;
-static constexpr uint32_t XF86XK_Launch6 = 0x1008FF46;
-static constexpr uint32_t XF86XK_Launch7 = 0x1008FF47;
-static constexpr uint32_t XF86XK_Launch8 = 0x1008FF48;
-static constexpr uint32_t XF86XK_Launch9 = 0x1008FF49;
-static constexpr uint32_t XF86XK_LaunchA = 0x1008FF4A;
-static constexpr uint32_t XF86XK_LaunchB = 0x1008FF4B;
-static constexpr uint32_t XF86XK_CD = 0x1008FF53;
-static constexpr uint32_t XF86XK_Clear = 0x1008FF55;
-static constexpr uint32_t XF86XK_Close = 0x1008FF56;
-static constexpr uint32_t XF86XK_Copy = 0x1008FF57;
-static constexpr uint32_t XF86XK_Cut = 0x1008FF58;
-static constexpr uint32_t XF86XK_Display = 0x1008FF59;
-static constexpr uint32_t XF86XK_Excel = 0x1008FF5C;
-static constexpr uint32_t XF86XK_Explorer = 0x1008FF5D;
-static constexpr uint32_t XF86XK_LogOff = 0x1008FF61;
-static constexpr uint32_t XF86XK_MenuKB = 0x1008FF65;
-static constexpr uint32_t XF86XK_MenuPB = 0x1008FF66;
-static constexpr uint32_t XF86XK_New = 0x1008FF68;
-static constexpr uint32_t XF86XK_News = 0x1008FF69;
-static constexpr uint32_t XF86XK_OfficeHome = 0x1008FF6A;
-static constexpr uint32_t XF86XK_Open = 0x1008FF6B;
-static constexpr uint32_t XF86XK_Paste = 0x1008FF6D;
-static constexpr uint32_t XF86XK_Reply = 0x1008FF72;
-static constexpr uint32_t XF86XK_Reload = 0x1008FF73;
-static constexpr uint32_t XF86XK_Save = 0x1008FF77;
-static constexpr uint32_t XF86XK_ScrollUp = 0x1008FF78;
-static constexpr uint32_t XF86XK_ScrollDown = 0x1008FF79;
-static constexpr uint32_t XF86XK_Send = 0x1008FF7B;
-static constexpr uint32_t XF86XK_Spell = 0x1008FF7C;
-static constexpr uint32_t XF86XK_SplitScreen = 0x1008FF7D;
-static constexpr uint32_t XF86XK_Tools = 0x1008FF81;
-static constexpr uint32_t XF86XK_Video = 0x1008FF87;
-static constexpr uint32_t XF86XK_Word = 0x1008FF89;
-static constexpr uint32_t XF86XK_ZoomIn = 0x1008FF8B;
-static constexpr uint32_t XF86XK_ZoomOut = 0x1008FF8C;
-static constexpr uint32_t XF86XK_WebCam = 0x1008FF8F;
-static constexpr uint32_t XF86XK_MailForward = 0x1008FF90;
-static constexpr uint32_t XF86XK_Music = 0x1008FF92;
-static constexpr uint32_t XF86XK_WLAN = 0x1008FF95;
-static constexpr uint32_t XF86XK_AudioForward = 0x1008FF97;
-static constexpr uint32_t XF86XK_AudioRandomPlay = 0x1008FF99;
-static constexpr uint32_t XF86XK_Subtitle = 0x1008FF9A;
-static constexpr uint32_t XF86XK_Select = 0x1008FFA0;
-static constexpr uint32_t XF86XK_Suspend = 0x1008FFA7;
-static constexpr uint32_t XF86XK_Hibernate = 0x1008FFA8;
+#include "third_party/x11proto/keysymdef.h"
#endif // UI_GFX_X_KEYSYMS_KEYSYMS_H_
diff --git a/chromium/ui/gfx/x/scoped_ignore_errors.cc b/chromium/ui/gfx/x/scoped_ignore_errors.cc
new file mode 100644
index 00000000000..0d9e6dff0af
--- /dev/null
+++ b/chromium/ui/gfx/x/scoped_ignore_errors.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 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 "ui/gfx/x/scoped_ignore_errors.h"
+
+namespace x11 {
+
+namespace {
+
+void IgnoreErrors(const x11::Error* error, const char* request_name) {}
+
+} // namespace
+
+ScopedIgnoreErrors::ScopedIgnoreErrors(Connection* connection)
+ : connection_(connection) {
+ old_error_handler_ =
+ connection_->SetErrorHandler(base::BindRepeating(IgnoreErrors));
+}
+
+ScopedIgnoreErrors::~ScopedIgnoreErrors() {
+ connection_->SetErrorHandler(old_error_handler_);
+}
+
+} // namespace x11
diff --git a/chromium/ui/gfx/x/scoped_ignore_errors.h b/chromium/ui/gfx/x/scoped_ignore_errors.h
new file mode 100644
index 00000000000..baa48b5fd5a
--- /dev/null
+++ b/chromium/ui/gfx/x/scoped_ignore_errors.h
@@ -0,0 +1,26 @@
+// Copyright 2020 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.
+
+#ifndef UI_GFX_X_SCOPED_IGNORE_ERRORS_H_
+#define UI_GFX_X_SCOPED_IGNORE_ERRORS_H_
+
+#include "base/component_export.h"
+#include "ui/gfx/x/connection.h"
+
+namespace x11 {
+
+// Sets a no-op error handler for a connection while this class is alive.
+class COMPONENT_EXPORT(X11) ScopedIgnoreErrors {
+ public:
+ explicit ScopedIgnoreErrors(Connection* connection);
+ ~ScopedIgnoreErrors();
+
+ private:
+ Connection* const connection_;
+ Connection::ErrorHandler old_error_handler_;
+};
+
+} // namespace x11
+
+#endif // UI_GFX_X_SCOPED_IGNORE_ERRORS_H_
diff --git a/chromium/ui/gfx/x/x11.h b/chromium/ui/gfx/x/x11.h
deleted file mode 100644
index a19c26e01bb..00000000000
--- a/chromium/ui/gfx/x/x11.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 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.
-
-// This header file replaces <X11/Xlib.h>. https://crbug.com/1066670 is
-// tracking removing usage of Xlib altogether. Do not add more Xlib
-// declarations here. The intention is to incrementally remove declarations
-// until there is nothing left, at which point this file will be removed.
-
-#ifndef UI_GFX_X_X11_H_
-#define UI_GFX_X_X11_H_
-
-#include "ui/gfx/x/connection.h"
-
-// Temporarily declare Xlib symbols we require. Do not add more Xlib
-// declarations here and do not include anything from <X11/*>.
-
-extern "C" {
-
-using Status = int;
-using Bool = int;
-using XID = unsigned long;
-using KeySym = XID;
-using KeyCode = unsigned char;
-using Window = XID;
-using Pixmap = XID;
-using Font = XID;
-using VisualID = unsigned long;
-using XPointer = char*;
-using Colormap = XID;
-using Cursor = XID;
-using Atom = unsigned long;
-using Time = unsigned long;
-using GC = struct _XGC*;
-using Display = struct _XDisplay;
-using xcb_connection_t = struct xcb_connection_t;
-
-enum XEventQueueOwner { XlibOwnsEventQueue = 0, XCBOwnsEventQueue };
-
-using XErrorEvent = struct _XErrorEvent {
- int type;
- Display* display;
- XID resourceid;
- unsigned long serial;
- unsigned char error_code;
- unsigned char request_code;
- unsigned char minor_code;
-};
-
-using XErrorHandler = int (*)(Display*, XErrorEvent*);
-using XIOErrorHandler = int (*)(Display*);
-
-Status XInitThreads(void);
-Display* XOpenDisplay(const char*);
-int XCloseDisplay(Display*);
-int XFlush(Display*);
-xcb_connection_t* XGetXCBConnection(Display* dpy);
-void XSetEventQueueOwner(Display* dpy, enum XEventQueueOwner owner);
-unsigned long XLastKnownRequestProcessed(Display*);
-int (*XSynchronize(Display*, Bool))(Display*);
-int XGetErrorDatabaseText(Display*,
- const char*,
- const char*,
- const char*,
- char*,
- int);
-int XGetErrorText(Display*, int, char*, int);
-XErrorHandler XSetErrorHandler(XErrorHandler);
-XIOErrorHandler XSetIOErrorHandler(XIOErrorHandler);
-int XStoreName(Display*, Window, const char*);
-}
-
-#endif // UI_GFX_X_X11_H_
diff --git a/chromium/ui/gfx/x/x11_atom_cache.cc b/chromium/ui/gfx/x/x11_atom_cache.cc
index cf727cd23cf..767bf21124b 100644
--- a/chromium/ui/gfx/x/x11_atom_cache.cc
+++ b/chromium/ui/gfx/x/x11_atom_cache.cc
@@ -257,7 +257,10 @@ X11AtomCache::X11AtomCache() : connection_(x11::Connection::Get()) {
std::vector<x11::Future<x11::InternAtomReply>> requests;
requests.reserve(kCacheCount);
for (const char* name : kAtomsToCache)
- requests.push_back(connection_->InternAtom({.name = name}));
+ requests.push_back(
+ connection_->InternAtom(x11::InternAtomRequest{.name = name}));
+ // Flush so all requests are sent before waiting on any replies.
+ connection_->Flush();
for (size_t i = 0; i < kCacheCount; ++i) {
if (auto response = requests[i].Sync())
cached_atoms_[kAtomsToCache[i]] = static_cast<x11::Atom>(response->atom);
@@ -272,7 +275,9 @@ x11::Atom X11AtomCache::GetAtom(const std::string& name) const {
return it->second;
x11::Atom atom = x11::Atom::None;
- if (auto response = connection_->InternAtom({.name = name}).Sync()) {
+ if (auto response =
+ connection_->InternAtom(x11::InternAtomRequest{.name = name})
+ .Sync()) {
atom = static_cast<x11::Atom>(response->atom);
cached_atoms_.emplace(name, atom);
} else {
diff --git a/chromium/ui/gfx/x/x11_atom_cache.h b/chromium/ui/gfx/x/x11_atom_cache.h
index 53fb799875f..03b8f4a50df 100644
--- a/chromium/ui/gfx/x/x11_atom_cache.h
+++ b/chromium/ui/gfx/x/x11_atom_cache.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "ui/gfx/gfx_export.h"
-#include "ui/gfx/x/x11_types.h"
+#include "ui/gfx/x/xproto.h"
namespace base {
template <typename T>
diff --git a/chromium/ui/gfx/x/x11_error_tracker.cc b/chromium/ui/gfx/x/x11_error_tracker.cc
deleted file mode 100644
index 5859a5e4b39..00000000000
--- a/chromium/ui/gfx/x/x11_error_tracker.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 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 "ui/gfx/x/x11_error_tracker.h"
-
-#include "base/check.h"
-#include "ui/gfx/x/x11.h"
-#include "ui/gfx/x/x11_types.h"
-
-namespace {
-
-unsigned char g_x11_error_code = 0;
-
-int X11ErrorHandler(Display* display, XErrorEvent* error) {
- g_x11_error_code = error->error_code;
- return 0;
-}
-
-} // namespace
-
-namespace gfx {
-
-X11ErrorTracker::X11ErrorTracker() {
- x11::Connection::Get()->Sync();
- old_handler_ = reinterpret_cast<void*>(XSetErrorHandler(X11ErrorHandler));
- g_x11_error_code = 0;
-}
-
-X11ErrorTracker::~X11ErrorTracker() {
- XSetErrorHandler(reinterpret_cast<XErrorHandler>(old_handler_));
-}
-
-bool X11ErrorTracker::FoundNewError() {
- x11::Connection::Get()->Sync();
- unsigned char error = g_x11_error_code;
- g_x11_error_code = 0;
- return error != 0;
-}
-
-} // namespace gfx
diff --git a/chromium/ui/gfx/x/x11_error_tracker.h b/chromium/ui/gfx/x/x11_error_tracker.h
deleted file mode 100644
index df06befc87f..00000000000
--- a/chromium/ui/gfx/x/x11_error_tracker.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef UI_GFX_X_X11_ERROR_TRACKER_H_
-#define UI_GFX_X_X11_ERROR_TRACKER_H_
-
-#include "base/macros.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-// X11ErrorTracker catches X11 errors in a non-fatal way. It does so by
-// temporarily changing the X11 error handler. The old error handler is
-// restored when the tracker is destroyed.
-class GFX_EXPORT X11ErrorTracker {
- public:
- X11ErrorTracker();
- ~X11ErrorTracker();
-
- // Returns whether an X11 error happened since this function was last called
- // (or since the creation of the tracker). This is potentially expensive,
- // since this causes a sync with the X server.
- bool FoundNewError();
-
- private:
- // The real type of |old_handler_| is XErrorHandler, or "int
- // (*handler)(Display *, XErrorEvent *)". However, XErrorEvent cannot be
- // forward declared, so void* is necessary here.
- void* old_handler_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(X11ErrorTracker);
-};
-
-} // namespace gfx
-
-#endif // UI_GFX_X_X11_ERROR_TRACKER_H_
diff --git a/chromium/ui/gfx/x/x11_path.cc b/chromium/ui/gfx/x/x11_path.cc
index 987d58345c2..823b8b617aa 100644
--- a/chromium/ui/gfx/x/x11_path.cc
+++ b/chromium/ui/gfx/x/x11_path.cc
@@ -8,7 +8,6 @@
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/gfx/x/x11.h"
namespace gfx {
diff --git a/chromium/ui/gfx/x/x11_types.cc b/chromium/ui/gfx/x/x11_types.cc
deleted file mode 100644
index 3e09d3e6a55..00000000000
--- a/chromium/ui/gfx/x/x11_types.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2013 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 "ui/gfx/x/x11_types.h"
-
-#include <string.h>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "ui/gfx/x/connection.h"
-#include "ui/gfx/x/x11.h"
-#include "ui/gfx/x/x11_switches.h"
-
-namespace gfx {
-
-XDisplay* GetXDisplay() {
- return x11::Connection::Get()->display();
-}
-
-} // namespace gfx
diff --git a/chromium/ui/gfx/x/x11_types.h b/chromium/ui/gfx/x/x11_types.h
deleted file mode 100644
index 4b6b9ec0043..00000000000
--- a/chromium/ui/gfx/x/x11_types.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef UI_GFX_X_X11_UTIL_H_
-#define UI_GFX_X_X11_UTIL_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "ui/gfx/gfx_export.h"
-#include "ui/gfx/x/connection.h"
-
-typedef unsigned long XID;
-typedef unsigned long VisualID;
-typedef union _XEvent XEvent;
-typedef struct _XImage XImage;
-typedef struct _XGC* GC;
-typedef struct _XDisplay XDisplay;
-typedef struct _XRegion XRegion;
-typedef struct __GLXFBConfigRec* GLXFBConfig;
-typedef XID GLXWindow;
-typedef XID GLXDrawable;
-
-extern "C" {
-int XFree(void*);
-}
-
-namespace gfx {
-
-template <class T, class R, R (*F)(T*)>
-struct XObjectDeleter {
- inline void operator()(void* ptr) const { F(static_cast<T*>(ptr)); }
-};
-
-template <class T, class D = XObjectDeleter<void, int, XFree>>
-using XScopedPtr = std::unique_ptr<T, D>;
-
-// Get the XDisplay singleton. Prefer x11::Connection::Get() instead.
-GFX_EXPORT XDisplay* GetXDisplay();
-
-} // namespace gfx
-
-#endif // UI_GFX_X_X11_UTIL_H_
diff --git a/chromium/ui/gfx/x/xlib.h b/chromium/ui/gfx/x/xlib.h
new file mode 100644
index 00000000000..68f4d3ec00e
--- /dev/null
+++ b/chromium/ui/gfx/x/xlib.h
@@ -0,0 +1,17 @@
+// Copyright 2020 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.
+
+#ifndef UI_GFX_X_XLIB_H_
+#define UI_GFX_X_XLIB_H_
+
+extern "C" {
+int XInitThreads(void);
+struct _XDisplay* XOpenDisplay(const char*);
+int XCloseDisplay(struct _XDisplay*);
+int XFlush(struct _XDisplay*);
+int XSynchronize(struct _XDisplay*, int);
+int XSetErrorHandler(int (*)(void*, void*));
+}
+
+#endif // UI_GFX_X_XLIB_H_
diff --git a/chromium/ui/gfx/x/xlib_support.cc b/chromium/ui/gfx/x/xlib_support.cc
new file mode 100644
index 00000000000..fe7846d0e9f
--- /dev/null
+++ b/chromium/ui/gfx/x/xlib_support.cc
@@ -0,0 +1,101 @@
+// Copyright 2020 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 "ui/gfx/x/xlib_support.h"
+
+#include "base/check.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "library_loaders/xlib_loader.h"
+
+namespace x11 {
+
+namespace {
+
+int XlibErrorHandler(void*, void*) {
+ DVLOG(1) << "Xlib error received";
+ return 0;
+}
+
+XlibLoader* GetXlibLoader() {
+ static base::NoDestructor<XlibLoader> xlib_loader;
+ return xlib_loader.get();
+}
+
+} // namespace
+
+DISABLE_CFI_ICALL
+void InitXlib() {
+ auto* xlib_loader = GetXlibLoader();
+ if (xlib_loader->loaded())
+ return;
+
+ CHECK(xlib_loader->Load("libX11.so.6"));
+
+ CHECK(xlib_loader->XInitThreads());
+
+ // The default Xlib error handler calls exit(1), which we don't want. This
+ // shouldn't happen in the browser process since only XProto requests are
+ // made, but in the GPU process, GLX can make Xlib requests, so setting an
+ // error handler is necessary. Importantly, there's also an IO error handler,
+ // and Xlib always calls exit(1) with no way to change this behavior.
+ SetXlibErrorHandler();
+}
+
+DISABLE_CFI_ICALL
+void SetXlibErrorHandler() {
+ GetXlibLoader()->XSetErrorHandler(XlibErrorHandler);
+}
+
+DISABLE_CFI_ICALL
+XlibDisplay::XlibDisplay(const std::string& address) {
+ InitXlib();
+
+ display_ = GetXlibLoader()->XOpenDisplay(address.empty() ? nullptr
+ : address.c_str());
+}
+
+DISABLE_CFI_ICALL
+XlibDisplay::~XlibDisplay() {
+ if (display_)
+ GetXlibLoader()->XCloseDisplay(display_);
+}
+
+DISABLE_CFI_ICALL
+XlibDisplayWrapper::XlibDisplayWrapper(struct _XDisplay* display,
+ XlibDisplayType type)
+ : display_(display), type_(type) {
+ if (!display_)
+ return;
+ if (type == XlibDisplayType::kSyncing)
+ GetXlibLoader()->XSynchronize(display_, true);
+}
+
+DISABLE_CFI_ICALL
+XlibDisplayWrapper::~XlibDisplayWrapper() {
+ if (!display_)
+ return;
+ if (type_ == XlibDisplayType::kFlushing)
+ GetXlibLoader()->XFlush(display_);
+ else if (type_ == XlibDisplayType::kSyncing)
+ GetXlibLoader()->XSynchronize(display_, false);
+}
+
+XlibDisplayWrapper::XlibDisplayWrapper(XlibDisplayWrapper&& other) {
+ display_ = other.display_;
+ type_ = other.type_;
+ other.display_ = nullptr;
+ other.type_ = XlibDisplayType::kNormal;
+}
+
+XlibDisplayWrapper& XlibDisplayWrapper::operator=(XlibDisplayWrapper&& other) {
+ display_ = other.display_;
+ type_ = other.type_;
+ other.display_ = nullptr;
+ other.type_ = XlibDisplayType::kNormal;
+ return *this;
+}
+
+} // namespace x11
diff --git a/chromium/ui/gfx/x/xlib_support.h b/chromium/ui/gfx/x/xlib_support.h
new file mode 100644
index 00000000000..37ea34afcbd
--- /dev/null
+++ b/chromium/ui/gfx/x/xlib_support.h
@@ -0,0 +1,73 @@
+// Copyright 2020 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.
+
+#ifndef UI_GFX_X_XLIB_SUPPORT_H_
+#define UI_GFX_X_XLIB_SUPPORT_H_
+
+#include <string>
+
+#include "base/component_export.h"
+
+struct _XDisplay;
+
+namespace x11 {
+
+// Specifies the behavior of XlibDisplayWrapper.
+enum class XlibDisplayType {
+ // No action taken on wrapper construction or destruction.
+ kNormal,
+
+ // Flushes the connection on destruction.
+ kFlushing,
+
+ // Synchronizes all requests while the wrapper is alive.
+ kSyncing,
+};
+
+// Loads Xlib, initializes threads, and sets a default error handler.
+COMPONENT_EXPORT(X11) void InitXlib();
+
+// Sets an async error handler which only logs an error message.
+COMPONENT_EXPORT(X11) void SetXlibErrorHandler();
+
+// A scoped Xlib display.
+class COMPONENT_EXPORT(X11) XlibDisplay {
+ public:
+ ~XlibDisplay();
+
+ private:
+ friend class Connection;
+ friend class XlibDisplayWrapper;
+
+ explicit XlibDisplay(const std::string& address);
+
+ struct _XDisplay* display_ = nullptr;
+};
+
+// A temporary wrapper around an unowned Xlib display that adds behavior
+// on construction and destruction (see XlibDisplayType).
+class COMPONENT_EXPORT(X11) XlibDisplayWrapper {
+ public:
+ ~XlibDisplayWrapper();
+
+ struct _XDisplay* display() {
+ return display_;
+ }
+ operator struct _XDisplay *() { return display_; }
+
+ XlibDisplayWrapper(XlibDisplayWrapper&& other);
+ XlibDisplayWrapper& operator=(XlibDisplayWrapper&& other);
+
+ private:
+ XlibDisplayWrapper(struct _XDisplay* display, XlibDisplayType type);
+
+ friend class Connection;
+
+ struct _XDisplay* display_;
+ XlibDisplayType type_;
+};
+
+} // namespace x11
+
+#endif // UI_GFX_X_XLIB_SUPPORT_H_
diff --git a/chromium/ui/gfx/x/xproto_internal.cc b/chromium/ui/gfx/x/xproto_internal.cc
index 83b8156a1dc..8a23cfc6da7 100644
--- a/chromium/ui/gfx/x/xproto_internal.cc
+++ b/chromium/ui/gfx/x/xproto_internal.cc
@@ -8,7 +8,6 @@
#include <xcb/xcb.h>
#include <xcb/xcbext.h>
-#include "ui/gfx/x/x11.h"
namespace x11 {
diff --git a/chromium/ui/gfx/x/xproto_internal.h b/chromium/ui/gfx/x/xproto_internal.h
index 61b930108ee..6ba0604db48 100644
--- a/chromium/ui/gfx/x/xproto_internal.h
+++ b/chromium/ui/gfx/x/xproto_internal.h
@@ -37,6 +37,9 @@ struct EnumBase<T, typename std::enable_if_t<std::is_enum<T>::value>> {
template <typename T>
using EnumBaseType = typename EnumBase<T>::type;
+template <typename T>
+void ReadError(T* error, ReadBuffer* buf);
+
// Calls free() on the underlying data when the count drops to 0.
class COMPONENT_EXPORT(X11) MallocedRefCountedMemory
: public base::RefCountedMemory {
@@ -137,10 +140,12 @@ base::Optional<unsigned int> SendRequestImpl(x11::Connection* connection,
template <typename Reply>
Future<Reply> SendRequest(x11::Connection* connection,
WriteBuffer* buf,
- bool reply_has_fds) {
+ bool reply_has_fds,
+ const char* request_name) {
auto sequence = SendRequestImpl(connection, buf, std::is_void<Reply>::value,
reply_has_fds);
- return {sequence ? connection : nullptr, sequence};
+ return {sequence ? connection : nullptr, sequence,
+ sequence ? request_name : nullptr};
}
// Helper function for xcbproto popcount. Given an integral type, returns the
diff --git a/chromium/ui/gfx/x/xproto_types.cc b/chromium/ui/gfx/x/xproto_types.cc
index 839d5466f52..af509848f09 100644
--- a/chromium/ui/gfx/x/xproto_types.cc
+++ b/chromium/ui/gfx/x/xproto_types.cc
@@ -7,9 +7,9 @@
#include <xcb/xcbext.h>
#include "base/memory/scoped_refptr.h"
+#include "base/trace_event/trace_event.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/xproto_internal.h"
-#include "ui/gfx/x/xproto_util.h"
namespace x11 {
@@ -80,8 +80,11 @@ void WriteBuffer::AppendCurrentBuffer() {
}
FutureBase::FutureBase(Connection* connection,
- base::Optional<unsigned int> sequence)
- : connection_(connection), sequence_(sequence) {}
+ base::Optional<unsigned int> sequence,
+ const char* request_name)
+ : connection_(connection),
+ sequence_(sequence),
+ request_name_(request_name) {}
// If a user-defined response-handler is not installed before this object goes
// out of scope, a default response handler will be installed. The default
@@ -91,45 +94,58 @@ FutureBase::~FutureBase() {
return;
OnResponseImpl(base::BindOnce(
- [](Connection* connection, RawReply reply, RawError error) {
- if (!error)
+ [](Connection* connection, const char* request_name,
+ Connection::ErrorHandler error_handler, RawReply raw_reply,
+ RawError raw_error) {
+ if (!raw_error)
return;
- x11::LogErrorEventDescription(error->full_sequence, error->error_code,
- error->major_code, error->minor_code);
+ auto error = connection->ParseError(raw_error);
+ error_handler.Run(error.get(), request_name);
},
- connection_));
+ connection_, request_name_, connection_->error_handler_));
}
FutureBase::FutureBase(FutureBase&& future)
- : connection_(future.connection_), sequence_(future.sequence_) {
- future.connection_ = nullptr;
- future.sequence_ = base::nullopt;
+ : connection_(future.connection_),
+ sequence_(future.sequence_),
+ request_name_(future.request_name_) {
+ future.Reset();
}
FutureBase& FutureBase::operator=(FutureBase&& future) {
connection_ = future.connection_;
sequence_ = future.sequence_;
- future.connection_ = nullptr;
- future.sequence_ = base::nullopt;
+ request_name_ = future.request_name_;
+ future.Reset();
return *this;
}
-void FutureBase::SyncImpl(Error** raw_error,
- scoped_refptr<base::RefCountedMemory>* raw_reply) {
+void FutureBase::SyncImpl(RawError* raw_error, RawReply* raw_reply) {
if (!sequence_)
return;
- auto* reply = reinterpret_cast<uint8_t*>(
- xcb_wait_for_reply(connection_->XcbConnection(), *sequence_, raw_error));
+ xcb_generic_error_t* error = nullptr;
+ void* reply = nullptr;
+ if (!xcb_poll_for_reply(connection_->XcbConnection(), *sequence_, &reply,
+ &error)) {
+ TRACE_EVENT1("ui", "xcb_wait_for_reply", "request", request_name_);
+ reply =
+ xcb_wait_for_reply(connection_->XcbConnection(), *sequence_, &error);
+ }
if (reply)
*raw_reply = base::MakeRefCounted<MallocedRefCountedMemory>(reply);
+ if (error)
+ *raw_error = base::MakeRefCounted<MallocedRefCountedMemory>(error);
sequence_ = base::nullopt;
}
-void FutureBase::SyncImpl(Error** raw_error) {
+void FutureBase::SyncImpl(RawError* raw_error) {
if (!sequence_)
return;
- *raw_error = xcb_request_check(connection_->XcbConnection(), {*sequence_});
+ if (xcb_generic_error_t* error =
+ xcb_request_check(connection_->XcbConnection(), {*sequence_})) {
+ *raw_error = base::MakeRefCounted<MallocedRefCountedMemory>(error);
+ }
sequence_ = base::nullopt;
}
@@ -140,4 +156,18 @@ void FutureBase::OnResponseImpl(ResponseCallback callback) {
sequence_ = base::nullopt;
}
+// static
+std::unique_ptr<Error> FutureBase::ParseErrorImpl(x11::Connection* connection,
+ RawError raw_error) {
+ if (!raw_error)
+ return nullptr;
+ return connection->ParseError(raw_error);
+}
+
+void FutureBase::Reset() {
+ connection_ = nullptr;
+ sequence_ = base::nullopt;
+ request_name_ = nullptr;
+}
+
} // namespace x11
diff --git a/chromium/ui/gfx/x/xproto_types.h b/chromium/ui/gfx/x/xproto_types.h
index 37799e76dfd..e38c83f561d 100644
--- a/chromium/ui/gfx/x/xproto_types.h
+++ b/chromium/ui/gfx/x/xproto_types.h
@@ -5,8 +5,6 @@
#ifndef UI_GFX_X_XPROTO_TYPES_H_
#define UI_GFX_X_XPROTO_TYPES_H_
-#include <xcb/xcb.h>
-
#include <cstdint>
#include <memory>
@@ -18,8 +16,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
-
-typedef struct _XDisplay XDisplay;
+#include "ui/gfx/x/error.h"
namespace x11 {
@@ -100,8 +97,6 @@ std::unique_ptr<Reply> ReadReply(ReadBuffer* buffer);
} // namespace detail
-using Error = xcb_generic_error_t;
-
template <class Reply>
class Future;
@@ -121,31 +116,29 @@ struct Response {
Reply* operator->() { return reply.get(); }
std::unique_ptr<Reply> reply;
- std::unique_ptr<Error, base::FreeDeleter> error;
+ std::unique_ptr<Error> error;
private:
friend class Future<Reply>;
- Response(std::unique_ptr<Reply> reply,
- std::unique_ptr<Error, base::FreeDeleter> error)
+ Response(std::unique_ptr<Reply> reply, std::unique_ptr<Error> error)
: reply(std::move(reply)), error(std::move(error)) {}
};
template <>
struct Response<void> {
- std::unique_ptr<Error, base::FreeDeleter> error;
+ std::unique_ptr<Error> error;
private:
friend class Future<void>;
- explicit Response(std::unique_ptr<Error, base::FreeDeleter> error)
- : error(std::move(error)) {}
+ explicit Response(std::unique_ptr<Error> error) : error(std::move(error)) {}
};
class COMPONENT_EXPORT(X11) FutureBase {
public:
using RawReply = scoped_refptr<base::RefCountedMemory>;
- using RawError = std::unique_ptr<xcb_generic_error_t, base::FreeDeleter>;
+ using RawError = scoped_refptr<base::RefCountedMemory>;
using ResponseCallback =
base::OnceCallback<void(RawReply reply, RawError error)>;
@@ -153,21 +146,30 @@ class COMPONENT_EXPORT(X11) FutureBase {
FutureBase& operator=(const FutureBase&) = delete;
protected:
- FutureBase(Connection* connection, base::Optional<unsigned int> sequence);
+ FutureBase(Connection* connection,
+ base::Optional<unsigned int> sequence,
+ const char* request_name);
~FutureBase();
FutureBase(FutureBase&& future);
FutureBase& operator=(FutureBase&& future);
- void SyncImpl(Error** raw_error,
- scoped_refptr<base::RefCountedMemory>* raw_reply);
- void SyncImpl(Error** raw_error);
+ void SyncImpl(RawError* raw_error, RawReply* raw_reply);
+ void SyncImpl(RawError* raw_error);
void OnResponseImpl(ResponseCallback callback);
+ x11::Connection* connection() { return connection_; }
+
+ static std::unique_ptr<Error> ParseErrorImpl(x11::Connection* connection,
+ RawError raw_error);
+
private:
- Connection* connection_;
+ void Reset();
+
+ Connection* connection_ = nullptr;
base::Optional<unsigned int> sequence_;
+ const char* request_name_ = nullptr;
};
// An x11::Future wraps an asynchronous response from the X11 server. The
@@ -178,12 +180,12 @@ class Future : public FutureBase {
public:
using Callback = base::OnceCallback<void(Response<Reply> response)>;
- Future() : FutureBase(nullptr, base::nullopt) {}
+ Future() : FutureBase(nullptr, base::nullopt, nullptr) {}
// Blocks until we receive the response from the server. Returns the response.
Response<Reply> Sync() {
- Error* raw_error = nullptr;
- scoped_refptr<base::RefCountedMemory> raw_reply;
+ RawError raw_error;
+ RawReply raw_reply;
SyncImpl(&raw_error, &raw_reply);
std::unique_ptr<Reply> reply;
@@ -192,9 +194,7 @@ class Future : public FutureBase {
reply = detail::ReadReply<Reply>(&buf);
}
- std::unique_ptr<Error, base::FreeDeleter> error;
- if (raw_error)
- error.reset(raw_error);
+ std::unique_ptr<Error> error = ParseErrorImpl(connection(), raw_error);
return {std::move(reply), std::move(error)};
}
@@ -205,13 +205,17 @@ class Future : public FutureBase {
// real Reply object before feeding the result to |callback|. This means
// |callback| must be bound as the first argument of the intermediate
// function.
- auto wrapper = [](Callback callback, RawReply raw_reply, RawError error) {
- ReadBuffer buf(raw_reply);
- std::unique_ptr<Reply> reply =
- raw_reply ? detail::ReadReply<Reply>(&buf) : nullptr;
+ auto wrapper = [](x11::Connection* connection, Callback callback,
+ RawReply raw_reply, RawError raw_error) {
+ std::unique_ptr<Reply> reply;
+ if (raw_reply) {
+ ReadBuffer buf(raw_reply);
+ reply = detail::ReadReply<Reply>(&buf);
+ }
+ std::unique_ptr<Error> error = ParseErrorImpl(connection, raw_error);
std::move(callback).Run({std::move(reply), std::move(error)});
};
- OnResponseImpl(base::BindOnce(wrapper, std::move(callback)));
+ OnResponseImpl(base::BindOnce(wrapper, connection(), std::move(callback)));
}
void IgnoreError() {
@@ -220,24 +224,21 @@ class Future : public FutureBase {
private:
template <typename R>
- friend Future<R> SendRequest(Connection*, WriteBuffer*, bool);
+ friend Future<R> SendRequest(Connection*, WriteBuffer*, bool, const char*);
- Future(Connection* connection, base::Optional<unsigned int> sequence)
- : FutureBase(connection, sequence) {}
+ Future(Connection* connection,
+ base::Optional<unsigned int> sequence,
+ const char* request_name)
+ : FutureBase(connection, sequence, request_name) {}
};
// Sync() specialization for requests that don't generate replies. The returned
// response will only contain an error if there was one.
template <>
inline Response<void> Future<void>::Sync() {
- Error* raw_error = nullptr;
+ RawError raw_error;
SyncImpl(&raw_error);
-
- std::unique_ptr<Error, base::FreeDeleter> error;
- if (raw_error)
- error.reset(raw_error);
-
- return Response<void>{std::move(error)};
+ return Response<void>{ParseErrorImpl(connection(), raw_error)};
}
// OnResponse() specialization for requests that don't generate replies. The
@@ -246,11 +247,12 @@ template <>
inline void Future<void>::OnResponse(Callback callback) {
// See Future<Reply>::OnResponse() for an explanation of why
// this wrapper is necessary.
- auto wrapper = [](Callback callback, RawReply reply, RawError error) {
+ auto wrapper = [](x11::Connection* connection, Callback callback,
+ RawReply reply, RawError error) {
DCHECK(!reply);
- std::move(callback).Run(Response<void>{std::move(error)});
+ std::move(callback).Run(Response<void>{ParseErrorImpl(connection, error)});
};
- OnResponseImpl(base::BindOnce(wrapper, std::move(callback)));
+ OnResponseImpl(base::BindOnce(wrapper, connection(), std::move(callback)));
}
template <>
diff --git a/chromium/ui/gfx/x/xproto_util.cc b/chromium/ui/gfx/x/xproto_util.cc
deleted file mode 100644
index 119fd902a46..00000000000
--- a/chromium/ui/gfx/x/xproto_util.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2020 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 "ui/gfx/x/xproto_util.h"
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "ui/gfx/x/connection.h"
-#include "ui/gfx/x/x11.h"
-#include "ui/gfx/x/xproto.h"
-
-namespace x11 {
-
-void LogErrorEventDescription(unsigned long serial,
- uint8_t error_code,
- uint8_t request_code,
- uint8_t minor_code) {
- // This function may make some expensive round trips (XListExtensions,
- // XQueryExtension), but the only effect this function has is LOG(WARNING),
- // so early-return if the log would never be sent anyway.
- if (!LOG_IS_ON(WARNING))
- return;
-
- char error_str[256];
- char request_str[256];
-
- x11::Connection* conn = x11::Connection::Get();
- auto* dpy = conn->display();
- XGetErrorText(dpy, error_code, error_str, sizeof(error_str));
-
- strncpy(request_str, "Unknown", sizeof(request_str));
- if (request_code < 128) {
- std::string num = base::NumberToString(request_code);
- XGetErrorDatabaseText(dpy, "XRequest", num.c_str(), "Unknown", request_str,
- sizeof(request_str));
- } else {
- if (auto response = conn->ListExtensions({}).Sync()) {
- for (const auto& str : response->names) {
- const char* name = str.name.c_str();
- auto query = conn->QueryExtension({name}).Sync();
- if (query && request_code == query->major_opcode) {
- std::string msg = base::StringPrintf("%s.%d", name, minor_code);
- XGetErrorDatabaseText(dpy, "XRequest", msg.c_str(), "Unknown",
- request_str, sizeof(request_str));
- break;
- }
- }
- }
- }
-
- LOG(WARNING) << "X error received: "
- << "serial " << serial << ", "
- << "error_code " << static_cast<int>(error_code) << " ("
- << error_str << "), "
- << "request_code " << static_cast<int>(request_code) << ", "
- << "minor_code " << static_cast<int>(minor_code) << " ("
- << request_str << ")";
-}
-
-} // namespace x11
diff --git a/chromium/ui/gfx/x/xproto_util.h b/chromium/ui/gfx/x/xproto_util.h
index 3a2486eb573..1b3b00578db 100644
--- a/chromium/ui/gfx/x/xproto_util.h
+++ b/chromium/ui/gfx/x/xproto_util.h
@@ -33,12 +33,6 @@ x11::Future<void> SendEvent(
return connection->SendEvent(send_event);
}
-COMPONENT_EXPORT(X11)
-void LogErrorEventDescription(unsigned long serial,
- uint8_t error_code,
- uint8_t request_code,
- uint8_t minor_code);
-
} // namespace x11
#endif // UI_GFX_X_XPROTO_UTIL_H_