blob: b7dc569b0d5988690b88782ebafe7d6294df6545 [file] [log] [blame]
// Copyright (c) 2012 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_atom_cache.h"
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram_functions.h"
#include "base/stl_util.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/future.h"
namespace x11 {
namespace {
struct {
const char* atom_name;
Atom atom_value;
} const kPredefinedAtoms[] = {
// {"PRIMARY", Atom::PRIMARY},
// {"SECONDARY", Atom::SECONDARY},
// {"ARC", Atom::ARC},
{"ATOM", Atom::ATOM},
// {"BITMAP", Atom::BITMAP},
{"CARDINAL", Atom::CARDINAL},
// {"COLORMAP", Atom::COLORMAP},
// {"CURSOR", Atom::CURSOR},
// {"CUT_BUFFER0", Atom::CUT_BUFFER0},
// {"CUT_BUFFER1", Atom::CUT_BUFFER1},
// {"CUT_BUFFER2", Atom::CUT_BUFFER2},
// {"CUT_BUFFER3", Atom::CUT_BUFFER3},
// {"CUT_BUFFER4", Atom::CUT_BUFFER4},
// {"CUT_BUFFER5", Atom::CUT_BUFFER5},
// {"CUT_BUFFER6", Atom::CUT_BUFFER6},
// {"CUT_BUFFER7", Atom::CUT_BUFFER7},
// {"DRAWABLE", Atom::DRAWABLE},
// {"FONT", Atom::FONT},
// {"INTEGER", Atom::INTEGER},
// {"PIXMAP", Atom::PIXMAP},
// {"POINT", Atom::POINT},
// {"RECTANGLE", Atom::RECTANGLE},
// {"RESOURCE_MANAGER", Atom::RESOURCE_MANAGER},
// {"RGB_COLOR_MAP", Atom::RGB_COLOR_MAP},
// {"RGB_BEST_MAP", Atom::RGB_BEST_MAP},
// {"RGB_BLUE_MAP", Atom::RGB_BLUE_MAP},
// {"RGB_DEFAULT_MAP", Atom::RGB_DEFAULT_MAP},
// {"RGB_GRAY_MAP", Atom::RGB_GRAY_MAP},
// {"RGB_GREEN_MAP", Atom::RGB_GREEN_MAP},
// {"RGB_RED_MAP", Atom::RGB_RED_MAP},
{"STRING", Atom::STRING},
// {"VISUALID", Atom::VISUALID},
// {"WINDOW", Atom::WINDOW},
// {"WM_COMMAND", Atom::WM_COMMAND},
// {"WM_HINTS", Atom::WM_HINTS},
// {"WM_CLIENT_MACHINE", Atom::WM_CLIENT_MACHINE},
// {"WM_ICON_NAME", Atom::WM_ICON_NAME},
// {"WM_ICON_SIZE", Atom::WM_ICON_SIZE},
// {"WM_NAME", Atom::WM_NAME},
// {"WM_NORMAL_HINTS", Atom::WM_NORMAL_HINTS},
// {"WM_SIZE_HINTS", Atom::WM_SIZE_HINTS},
// {"WM_ZOOM_HINTS", Atom::WM_ZOOM_HINTS},
// {"MIN_SPACE", Atom::MIN_SPACE},
// {"NORM_SPACE", Atom::NORM_SPACE},
// {"MAX_SPACE", Atom::MAX_SPACE},
// {"END_SPACE", Atom::END_SPACE},
// {"SUPERSCRIPT_X", Atom::SUPERSCRIPT_X},
// {"SUPERSCRIPT_Y", Atom::SUPERSCRIPT_Y},
// {"SUBSCRIPT_X", Atom::SUBSCRIPT_X},
// {"SUBSCRIPT_Y", Atom::SUBSCRIPT_Y},
// {"UNDERLINE_POSITION", Atom::UNDERLINE_POSITION},
// {"UNDERLINE_THICKNESS", Atom::UNDERLINE_THICKNESS},
// {"STRIKEOUT_ASCENT", Atom::STRIKEOUT_ASCENT},
// {"STRIKEOUT_DESCENT", Atom::STRIKEOUT_DESCENT},
// {"ITALIC_ANGLE", Atom::ITALIC_ANGLE},
// {"X_HEIGHT", Atom::X_HEIGHT},
// {"QUAD_WIDTH", Atom::QUAD_WIDTH},
// {"WEIGHT", Atom::WEIGHT},
// {"POINT_SIZE", Atom::POINT_SIZE},
// {"RESOLUTION", Atom::RESOLUTION},
// {"COPYRIGHT", Atom::COPYRIGHT},
// {"NOTICE", Atom::NOTICE},
// {"FONT_NAME", Atom::FONT_NAME},
// {"FAMILY_NAME", Atom::FAMILY_NAME},
// {"FULL_NAME", Atom::FULL_NAME},
// {"CAP_HEIGHT", Atom::CAP_HEIGHT},
{"WM_CLASS", Atom::WM_CLASS},
// {"WM_TRANSIENT_FOR", Atom::WM_TRANSIENT_FOR},
};
constexpr const char* kAtomsToCache[] = {
"ATOM_PAIR",
"Abs Dbl End Timestamp",
"Abs Dbl Fling X Velocity",
"Abs Dbl Fling Y Velocity",
"Abs Dbl Metrics Data 1",
"Abs Dbl Metrics Data 2",
"Abs Dbl Ordinal X",
"Abs Dbl Ordinal Y",
"Abs Dbl Start Timestamp",
"Abs Finger Count",
"Abs Fling State",
"Abs MT Orientation",
"Abs MT Position X",
"Abs MT Position Y",
"Abs MT Pressure",
"Abs MT Touch Major",
"Abs MT Touch Minor",
"Abs MT Tracking ID",
"Abs Metrics Type",
"CHECK",
"CHOME_SELECTION",
"CHROME_SELECTION",
"CHROMIUM_COMPOSITE_WINDOW",
"CHROMIUM_TIMESTAMP",
"CLIPBOARD",
"CLIPBOARD_MANAGER",
"Content Protection",
"Desired",
"Device Node",
"Device Product ID",
"EDID",
"Enabled",
"FAKE_SELECTION",
"Full aspect",
"INCR",
"KEYBOARD",
"LOCK",
"MOUSE",
"MULTIPLE",
"Rel Horiz Wheel",
"Rel Vert Wheel",
"SAVE_TARGETS",
"SELECTION_STRING",
"TARGET1",
"TARGET2",
"TARGETS",
"TEXT",
"TIMESTAMP",
"TOUCHPAD",
"TOUCHSCREEN",
"Tap Paused",
"Touch Timestamp",
"UTF8_STRING",
"Undesired",
"WM_DELETE_WINDOW",
"WM_PROTOCOLS",
"WM_WINDOW_ROLE",
"XdndActionAsk",
"XdndActionCopy",
"XdndActionDirectSave",
"XdndActionLink",
"XdndActionList",
"XdndActionMove",
"XdndActionPrivate",
"XdndAware",
"XdndDirectSave0",
"XdndDrop",
"XdndEnter",
"XdndFinished",
"XdndLeave",
"XdndPosition",
"XdndProxy",
"XdndSelection",
"XdndStatus",
"XdndTypeList",
"_CHROME_DISPLAY_INTERNAL",
"_CHROME_DISPLAY_ROTATION",
"_CHROME_DISPLAY_SCALE_FACTOR",
"_CHROMIUM_DRAG_RECEIVER",
"_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED",
"_GTK_THEME_VARIANT",
"_ICC_PROFILE",
"_MOTIF_WM_HINTS",
"_NETSCAPE_URL",
"_NET_ACTIVE_WINDOW",
"_NET_CLIENT_LIST_STACKING",
"_NET_CURRENT_DESKTOP",
"_NET_FRAME_EXTENTS",
"_NET_SUPPORTED",
"_NET_SUPPORTING_WM_CHECK",
"_NET_SYSTEM_TRAY_OPCODE",
"_NET_SYSTEM_TRAY_S0",
"_NET_SYSTEM_TRAY_VISUAL",
"_NET_WM_BYPASS_COMPOSITOR",
"_NET_WM_CM_S0",
"_NET_WM_DESKTOP",
"_NET_WM_ICON",
"_NET_WM_MOVERESIZE",
"_NET_WM_NAME",
"_NET_WM_PID",
"_NET_WM_PING",
"_NET_WM_STATE",
"_NET_WM_STATE_ABOVE",
"_NET_WM_STATE_FOCUSED",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_HIDDEN",
"_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_SKIP_TASKBAR",
"_NET_WM_STATE_STICKY",
"_NET_WM_SYNC_REQUEST",
"_NET_WM_SYNC_REQUEST_COUNTER",
"_NET_WM_USER_TIME",
"_NET_WM_WINDOW_OPACITY",
"_NET_WM_WINDOW_TYPE",
"_NET_WM_WINDOW_TYPE_DND",
"_NET_WM_WINDOW_TYPE_MENU",
"_NET_WM_WINDOW_TYPE_NORMAL",
"_NET_WM_WINDOW_TYPE_NOTIFICATION",
"_NET_WM_WINDOW_TYPE_TOOLTIP",
"_NET_WORKAREA",
"_SCREENSAVER_STATUS",
"_SCREENSAVER_VERSION",
"_XEMBED_INFO",
"application/octet-stream",
"application/vnd.chromium.test",
"chromium/filename",
"chromium/x-bookmark-entries",
"chromium/x-browser-actions",
"chromium/x-file-system-files",
"chromium/x-pepper-custom-data",
"chromium/x-renderer-taint",
"chromium/x-web-custom-data",
"chromium/x-webkit-paste",
"image/png",
"image/svg+xml",
"marker_event",
"scaling mode",
"text/html",
"text/plain",
"text/plain;charset=utf-8",
"text/rtf",
"text/uri-list",
"text/x-moz-url",
};
constexpr int kCacheCount = base::size(kAtomsToCache);
} // namespace
Atom GetAtom(const std::string& name) {
return X11AtomCache::GetInstance()->GetAtom(name);
}
X11AtomCache* X11AtomCache::GetInstance() {
return base::Singleton<X11AtomCache>::get();
}
X11AtomCache::X11AtomCache() : connection_(Connection::Get()) {
for (const auto& predefined_atom : kPredefinedAtoms)
cached_atoms_[predefined_atom.atom_name] = predefined_atom.atom_value;
std::vector<Future<InternAtomReply>> requests;
requests.reserve(kCacheCount);
for (const char* name : kAtomsToCache)
requests.push_back(
connection_->InternAtom(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<Atom>(response->atom);
}
}
X11AtomCache::~X11AtomCache() = default;
Atom X11AtomCache::GetAtom(const std::string& name) const {
const auto it = cached_atoms_.find(name);
if (it != cached_atoms_.end())
return it->second;
Atom atom = Atom::None;
if (auto response =
connection_->InternAtom(InternAtomRequest{.name = name}).Sync()) {
atom = static_cast<Atom>(response->atom);
cached_atoms_.emplace(name, atom);
} else {
static int error_count = 0;
++error_count;
// TODO(https://crbug.com/1000919): Evaluate and remove UMA metrics after
// enough data is gathered.
base::UmaHistogramCounts100("X11.XInternAtomFailure", error_count);
}
return atom;
}
} // namespace x11