blob: 0a626f9f01a16fbdec18f7ca60b7aa59e2265404 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// 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 "ui/gfx/x/connection.h"
#include "ui/gfx/x/future.h"
namespace x11 {
namespace {
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",
"_GTK_FRAME_EXTENTS",
"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_CURRENT_DESKTOP",
"_NET_FRAME_EXTENTS",
"_NET_STARTUP_INFO",
"_NET_STARTUP_INFO_BEGIN",
"_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_OPAQUE_REGION",
"_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_DIALOG",
"_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",
"xwayland-pointer",
"xwayland-keyboard",
"xwayland-touch",
};
constexpr int kCacheCount = std::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()) {
// Clipboard formats are keyed on their format string (eg. "STRING",
// "UTF8_STRING", "image/png"). Plumbing through x11::Atoms instead would be
// tricky, so set "STRING" here to prevent hitting the DCHECK_GT() in
// GetAtom().
cached_atoms_["STRING"] = x11::Atom::STRING;
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 = response->atom;
DCHECK_GT(atom, x11::Atom::kLastPredefinedAtom)
<< " Use x11::Atom::" << name << " instead of x11::GetAtom(\"" << name
<< "\")";
cached_atoms_.emplace(name, atom);
}
return atom;
}
} // namespace x11