dde-dock/frame/taskmanager/xcbutils.cpp
tsic404 9de057e2cc refactor: add taskmanager from dde-application-manager
1. taskmanager used to identify which entry should map to window
  in x11 environmrnt, listen to xevent in anohter thread, and handle those event
when window create, destory, changed. use some way to identify which entry(desktopfile)
should mapped to changed window.
  in wayland, connected plsamawindow signal(window created destoried.
2. use taskmanager instead of dbus in old dock code

log: as title
2023-07-18 07:35:19 +00:00

761 lines
22 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "xcbutils.h"
#include <cstdint>
#include <utility>
#include <iostream>
#include <cstring>
#include <memory>
#include <algorithm>
#include <X11/Xlib.h>
#include <X11/extensions/XRes.h>
XCBUtils::XCBUtils()
{
m_connect = xcb_connect(nullptr, &m_screenNum); // nullptr表示默认使用环境变量$DISPLAY获取屏幕
if (xcb_connection_has_error(m_connect)) {
std::cout << "XCBUtils: init xcb_connect error" << std::endl;
return;
}
if (!xcb_ewmh_init_atoms_replies(&m_ewmh,
xcb_ewmh_init_atoms(m_connect, &m_ewmh), // 初始化Atom
nullptr))
std::cout << "XCBUtils: init ewmh error" << std::endl;
}
XCBUtils::~XCBUtils()
{
if (m_connect) {
xcb_disconnect(m_connect); // 关闭连接并释放
m_connect = nullptr;
}
}
XWindow XCBUtils::allocId()
{
return xcb_generate_id(m_connect);
}
void XCBUtils::flush()
{
xcb_flush(m_connect);
}
void XCBUtils::killClientChecked(XWindow xid)
{
xcb_kill_client_checked(m_connect, xid);
}
xcb_get_property_reply_t *XCBUtils::getPropertyValueReply(XWindow xid, XCBAtom property, XCBAtom type)
{
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect,
0,
xid,
property,
type,
0,
MAXLEN);
return xcb_get_property_reply(m_connect, cookie, nullptr);
}
void *XCBUtils::getPropertyValue(XWindow xid, XCBAtom property, XCBAtom type)
{
void *value = nullptr;
xcb_get_property_reply_t *reply = getPropertyValueReply(xid, property, type);
if (reply) {
if (xcb_get_property_value_length(reply) > 0) {
value = xcb_get_property_value(reply);
}
free(reply);
}
return value;
}
std::string XCBUtils::getUTF8PropertyStr(XWindow xid, XCBAtom property)
{
std::string ret;
xcb_get_property_reply_t *reply = getPropertyValueReply(xid, property, m_ewmh.UTF8_STRING);
if (reply) {
ret = getUTF8StrFromReply(reply);
free(reply);
}
return ret;
}
XCBAtom XCBUtils::getAtom(const char *name)
{
XCBAtom ret = m_atomCache.getVal(name);
if (ret == ATOMNONE) {
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connect, false, strlen(name), name);
std::shared_ptr<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(m_connect, cookie, nullptr), [=](xcb_intern_atom_reply_t* reply){
free(reply);}
);
if (reply) {
m_atomCache.store(name, xcb_atom_t(reply->atom));
ret = reply->atom;
}
}
return ret;
}
std::string XCBUtils::getAtomName(XCBAtom atom)
{
std::string ret = m_atomCache.getName(atom);
if (ret.empty()) {
xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(m_connect, atom);
std::shared_ptr<xcb_get_atom_name_reply_t> reply(
xcb_get_atom_name_reply(m_connect, cookie, nullptr),
[=](xcb_get_atom_name_reply_t* reply) {free(reply);});
if (reply) {
char *name = xcb_get_atom_name_name(reply.get());
if (name) {
m_atomCache.store(name, atom);
ret = name;
}
}
}
return ret;
}
Geometry XCBUtils::getWindowGeometry(XWindow xid)
{
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xcb_drawable_t(xid));
std::shared_ptr<xcb_get_geometry_reply_t> reply(
xcb_get_geometry_reply(m_connect, cookie, nullptr),
[=](xcb_get_geometry_reply_t* reply){free(reply);}
);
if (!reply) {
std::cout << xid << " getWindowGeometry err" << std::endl;
return Geometry();
}
Geometry ret;
ret.x = reply->x;
ret.y = reply->y;
ret.width = reply->width;
ret.height = reply->height;
const xcb_setup_t *xcbSetup = xcb_get_setup(m_connect);
if (!xcbSetup)
return Geometry();
xcb_screen_iterator_t xcbScreenIterator = xcb_setup_roots_iterator(xcbSetup);
std::shared_ptr<xcb_translate_coordinates_reply_t> translateReply(
xcb_translate_coordinates_reply(m_connect,
xcb_translate_coordinates(m_connect, xid, xcbScreenIterator.data->root, 0, 0),
nullptr),
[=](xcb_translate_coordinates_reply_t* translateReply){free(translateReply);});
if (translateReply) {
ret.x = translateReply->dst_x;
ret.y = translateReply->dst_y;
}
XWindow dWin = getDecorativeWindow(xid);
reply.reset(xcb_get_geometry_reply(m_connect, xcb_get_geometry(m_connect, xcb_drawable_t(dWin)), nullptr),
[=](xcb_get_geometry_reply_t* reply){free(reply);});
if (!reply)
return ret;
if (reply->x == ret.x && reply->y == ret.y) {
// 无标题的窗口比如deepin-editor, dconf-editor等
WindowFrameExtents windowFrameRect = getWindowFrameExtents(xid);
if (!windowFrameRect.isNull()) {
int x = ret.x + windowFrameRect.Left;
int y = ret.y + windowFrameRect.Top;
int width = ret.width - (windowFrameRect.Left + windowFrameRect.Right);
int height = ret.height - (windowFrameRect.Top + windowFrameRect.Bottom);
ret.x = x;
ret.y = y;
ret.width = width;
ret.height = height;
}
}
return ret;
}
XWindow XCBUtils::getDecorativeWindow(XWindow xid)
{
XWindow winId = xid;
for (int i = 0; i < 10; i++) {
xcb_query_tree_cookie_t cookie = xcb_query_tree(m_connect, winId);
std::shared_ptr<xcb_query_tree_reply_t> reply(
xcb_query_tree_reply(m_connect, cookie, nullptr),
[=](xcb_query_tree_reply_t* reply){free(reply);}
);
if (!reply) return 0;
if (reply->root == reply->parent) return winId;
winId = reply->parent;
}
return 0;
}
WindowFrameExtents XCBUtils::getWindowFrameExtents(XWindow xid)
{
xcb_atom_t perp = getAtom("_NET_FRAME_EXTENTS");
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect, false, xid, perp, XCB_ATOM_CARDINAL, 0, 4);
std::shared_ptr<xcb_get_property_reply_t> reply(
xcb_get_property_reply(m_connect, cookie, nullptr),
[=](xcb_get_property_reply_t* reply){free(reply);}
);
if (!reply || reply->format == 0) {
perp = getAtom("_GTK_FRAME_EXTENTS");
cookie = xcb_get_property(m_connect, false, xid, perp, XCB_ATOM_CARDINAL, 0, 4);
reply.reset(xcb_get_property_reply(m_connect, cookie, nullptr), [=](xcb_get_property_reply_t* reply){free(reply);});
if (!reply)
return WindowFrameExtents();
}
if (reply->format != 32 || reply->value_len != 4) {
return WindowFrameExtents();
}
uint32_t *data = static_cast<uint32_t *>(xcb_get_property_value(reply.get()));
if (!data)
return WindowFrameExtents();
WindowFrameExtents winFrame(data[0], data[1], data[2], data[3]);
return winFrame;
}
XWindow XCBUtils::getActiveWindow()
{
XWindow ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window(&m_ewmh, m_screenNum);
if (!xcb_ewmh_get_active_window_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << "getActiveWindow error" << std::endl;
}
return ret;
}
void XCBUtils::setActiveWindow(XWindow xid)
{
xcb_ewmh_set_active_window(&m_ewmh, m_screenNum, xid);
}
void XCBUtils::changeActiveWindow(XWindow newActiveXid)
{
xcb_ewmh_request_change_active_window(&m_ewmh, m_screenNum, newActiveXid, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER, XCB_CURRENT_TIME, XCB_WINDOW_NONE);
flush();
}
void XCBUtils::restackWindow(XWindow xid)
{
xcb_ewmh_request_restack_window(&m_ewmh, m_screenNum, xid, 0, XCB_STACK_MODE_ABOVE);
}
std::list<XWindow> XCBUtils::getClientList()
{
std::list<XWindow> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list(&m_ewmh, m_screenNum);
xcb_ewmh_get_windows_reply_t reply;
if (xcb_ewmh_get_client_list_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.windows_len; i++) {
ret.push_back(reply.windows[i]);
}
xcb_ewmh_get_windows_reply_wipe(&reply);
} else {
std::cout << "getClientList error" << std::endl;
}
return ret;
}
std::list<XWindow> XCBUtils::getClientListStacking()
{
std::list<XWindow> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list_stacking(&m_ewmh, m_screenNum);
xcb_ewmh_get_windows_reply_t reply;
if (xcb_ewmh_get_client_list_stacking_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.windows_len; i++) {
ret.push_back(reply.windows[i]);
}
xcb_ewmh_get_windows_reply_wipe(&reply);
} else {
std::cout << "getClientListStacking error" << std::endl;
}
return ret;
}
std::vector<XCBAtom> XCBUtils::getWMState(XWindow xid)
{
std::vector<XCBAtom> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state(&m_ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atom
if (xcb_ewmh_get_wm_state_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
xcb_ewmh_get_atoms_reply_wipe(&reply);
} else {
std::cout << xid << " getWMState error" << std::endl;
}
return ret;
}
std::vector<XCBAtom> XCBUtils::getWMWindoType(XWindow xid)
{
std::vector<XCBAtom> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type(&m_ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atom
if (xcb_ewmh_get_wm_window_type_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
xcb_ewmh_get_atoms_reply_wipe(&reply);
} else {
std::cout << xid << " getWMWindoType error" << std::endl;
}
return ret;
}
std::vector<XCBAtom> XCBUtils::getWMAllowedActions(XWindow xid)
{
std::vector<XCBAtom> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_allowed_actions(&m_ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atoms
if (xcb_ewmh_get_wm_allowed_actions_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
xcb_ewmh_get_atoms_reply_wipe(&reply);
} else {
std::cout << xid << " getWMAllowedActions error" << std::endl;
}
return ret;
}
void XCBUtils::setWMAllowedActions(XWindow xid, std::vector<XCBAtom> actions)
{
XCBAtom list[MAXALLOWEDACTIONLEN] {0};
for (size_t i = 0; i < actions.size(); i++) {
list[i] = actions[i];
}
xcb_ewmh_set_wm_allowed_actions(&m_ewmh, xid, actions.size(), list);
}
std::string XCBUtils::getWMName(XWindow xid)
{
std::string ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name(&m_ewmh, xid);
xcb_ewmh_get_utf8_strings_reply_t reply;
if (xcb_ewmh_get_wm_name_reply(&m_ewmh, cookie, &reply, nullptr)) {
ret.assign(reply.strings, reply.strings_len);
// 释放utf8_strings_reply分配的内存
xcb_ewmh_get_utf8_strings_reply_wipe(&reply);
} else {
std::cout << xid << " getWMName error" << std::endl;
}
return ret;
}
uint32_t XCBUtils::getWMPid(XWindow xid)
{
// NOTE(black_desk): code copy from https://gitlab.gnome.org/GNOME/metacity/-/merge_requests/13/diffs
XResClientIdSpec spec = {
.client = xid,
.mask = XRES_CLIENT_ID_PID_MASK,
};
std::shared_ptr<Display> dpy = {
XOpenDisplay(nullptr),
[](Display *p){ XCloseDisplay(p); },
};
long num_ids;
XResClientIdValue *client_ids;
XResQueryClientIds(dpy.get(),
1,
&spec,
&num_ids,
&client_ids);
pid_t pid = -1;
for (long i = 0; i < num_ids; i++) {
if (client_ids[i].spec.mask == XRES_CLIENT_ID_PID_MASK) {
pid = XResGetClientPid(&client_ids[i]);
break;
}
}
XResClientIdsDestroy(num_ids, client_ids);
return pid;
}
std::string XCBUtils::getWMIconName(XWindow xid)
{
std::string ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name(&m_ewmh, xid);
xcb_ewmh_get_utf8_strings_reply_t reply;
if (!xcb_ewmh_get_wm_icon_name_reply(&m_ewmh, cookie, &reply, nullptr)) {
std::cout << xid << " getWMIconName error" << std::endl;
}
ret.assign(reply.strings);
return ret;
}
WMIcon XCBUtils::getWMIcon(XWindow xid)
{
WMIcon wmIcon{};
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon(&m_ewmh, xid);
xcb_ewmh_get_wm_icon_reply_t reply;
xcb_generic_error_t* error;
auto ret = xcb_ewmh_get_wm_icon_reply(&m_ewmh, cookie, &reply, &error);
if (error) {
std::cout << "failed to get wm icon" << error->error_code;
std::free(error);
return wmIcon;
}
if (ret) {
auto fcn = [](xcb_ewmh_wm_icon_iterator_t it) {
// https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm45582154990752
// The first two cardinals are width, height. Data is in rows, left to right and top to bottom
// Two cardinals means width and heighr, not offset.
const auto size = it.width * it.height;
std::vector<uint32_t> ret(size);
// data数据是按行从左至右从上至下排列
uint32_t *data = it.data;
if (!data) {
return ret;
}
std::copy_n(data, size, ret.begin());
return ret;
};
// 获取icon中size最大的图标
xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply);
xcb_ewmh_wm_icon_iterator_t wmIconIt{0, 0, nullptr};
for (; iter.rem; xcb_ewmh_get_wm_icon_next(&iter)) {
const uint32_t size = iter.width * iter.height;
if (size > 0 && size > wmIconIt.width * wmIconIt.height) {
wmIconIt = iter;
}
}
wmIcon = WMIcon{wmIconIt.width, wmIconIt.height, fcn(wmIconIt)};
xcb_ewmh_get_wm_icon_reply_wipe(&reply); // clear
}
return wmIcon;
}
XWindow XCBUtils::getWMClientLeader(XWindow xid)
{
XWindow ret = 0;
XCBAtom atom = getAtom("WM_CLIENT_LEADER");
void *value = getPropertyValue(xid, atom, XCB_ATOM_INTEGER);
if (value) {
ret = *(XWindow*)(value);
}
return ret;
}
void XCBUtils::requestCloseWindow(XWindow xid, uint32_t timestamp)
{
xcb_ewmh_request_close_window(&m_ewmh, m_screenNum, xid, timestamp, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER);
}
uint32_t XCBUtils::getWMDesktop(XWindow xid)
{
uint32_t ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop(&m_ewmh, xid);
if (!xcb_ewmh_get_wm_desktop_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << xid << " getWMDesktop error" << std::endl;
}
return ret;
}
void XCBUtils::setWMDesktop(XWindow xid, uint32_t desktop)
{
xcb_ewmh_set_wm_desktop(&m_ewmh, xid, desktop);
}
void XCBUtils::setCurrentWMDesktop(uint32_t desktop)
{
xcb_ewmh_set_current_desktop(&m_ewmh, m_screenNum, desktop);
}
void XCBUtils::changeCurrentDesktop(uint32_t newDesktop, uint32_t timestamp)
{
xcb_ewmh_request_change_current_desktop(&m_ewmh, m_screenNum, newDesktop, timestamp);
}
uint32_t XCBUtils::getCurrentWMDesktop()
{
uint32_t ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop(&m_ewmh, m_screenNum);
if (!xcb_ewmh_get_current_desktop_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << "getCurrentWMDesktop error" << std::endl;
}
return ret;
}
bool XCBUtils::isGoodWindow(XWindow xid)
{
bool ret = false;
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xid);
xcb_generic_error_t **errStore = nullptr;
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(m_connect, cookie, errStore);
if (reply) {
// 正常获取窗口geometry则判定为good
if (!errStore) {
ret = true;
} else {
free(errStore);
}
free(reply);
}
return ret;
}
// TODO XCB下无_MOTIF_WM_HINTS属性
MotifWMHints XCBUtils::getWindowMotifWMHints(XWindow xid)
{
XCBAtom atomWmHints = getAtom("_MOTIF_WM_HINTS");
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect, false, xid, atomWmHints, atomWmHints, 0, 5);
std::unique_ptr<xcb_get_property_reply_t> reply(xcb_get_property_reply(m_connect, cookie, nullptr));
if (!reply || reply->format != 32 || reply->value_len != 5)
return MotifWMHints{0, 0, 0, 0, 0};
uint32_t *data = static_cast<uint32_t *>(xcb_get_property_value(reply.get()));
MotifWMHints ret;
ret.flags = data[0];
ret.functions = data[1];
ret.decorations = data[2];
ret.inputMode = data[3];
ret.status = data[4];
return ret;
}
bool XCBUtils::hasXEmbedInfo(XWindow xid)
{
//XCBAtom atom = getAtom("_XEMBED_INFO");
return false;
}
XWindow XCBUtils::getWMTransientFor(XWindow xid)
{
XWindow ret;
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for(m_connect, xid);
if (!xcb_icccm_get_wm_transient_for_reply(m_connect, cookie, &ret, nullptr)) {
std::cout << xid << " getWMTransientFor error" << std::endl;
}
return ret;
}
uint32_t XCBUtils::getWMUserTime(XWindow xid)
{
uint32_t ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_user_time(&m_ewmh, xid);
if (!xcb_ewmh_get_wm_user_time_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << xid << " getWMUserTime error" << std::endl;
}
return ret;
}
int XCBUtils::getWMUserTimeWindow(XWindow xid)
{
XCBAtom ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_user_time_window(&m_ewmh, xid);
if (!xcb_ewmh_get_wm_user_time_window_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << xid << " getWMUserTimeWindow error" << std::endl;
}
return ret;
}
WMClass XCBUtils::getWMClass(XWindow xid)
{
WMClass ret;
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class(m_connect, xid);
xcb_icccm_get_wm_class_reply_t reply;
reply.instance_name = nullptr;
reply.class_name = nullptr;
xcb_icccm_get_wm_class_reply(m_connect, cookie, &reply, nullptr); // 返回值为0不一定表示失败 故不做返回值判断
if (reply.class_name)
ret.className.assign(reply.class_name);
if (reply.instance_name)
ret.instanceName.assign(reply.instance_name);
if (reply.class_name || reply.instance_name) {
xcb_icccm_get_wm_class_reply_wipe(&reply);
}
return ret;
}
void XCBUtils::minimizeWindow(XWindow xid)
{
uint32_t data[2];
data[0] = XCB_ICCCM_WM_STATE_ICONIC;
data[1] = XCB_NONE;
xcb_ewmh_send_client_message(m_connect, xid, getRootWindow(),getAtom("WM_CHANGE_STATE"), 2, data);
flush();
}
void XCBUtils::maxmizeWindow(XWindow xid)
{
xcb_ewmh_request_change_wm_state(&m_ewmh
, m_screenNum
, xid
, XCB_EWMH_WM_STATE_ADD
, getAtom("_NET_WM_STATE_MAXIMIZED_VERT")
, getAtom("_NET_WM_STATE_MAXIMIZED_HORZ")
, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER);
}
// TODO
std::vector<std::string> XCBUtils::getWMCommand(XWindow xid)
{
std::vector<std::string> ret;
xcb_get_property_reply_t *reply = getPropertyValueReply(xid, XCB_ATOM_WM_COMMAND, m_ewmh.UTF8_STRING);
if (reply) {
ret = getUTF8StrsFromReply(reply);
free(reply);
}
return ret;
}
std::string XCBUtils::getUTF8StrFromReply(xcb_get_property_reply_t *reply)
{
std::string ret;
if (!reply || reply->format != 8) {
return ret;
}
char data[12] = {0};
for (uint32_t i=0; i < reply->value_len; i++) {
data[i] = char(reply->pad0[i]);
}
ret.assign(data);
return ret;
}
std::vector<std::string> XCBUtils::getUTF8StrsFromReply(xcb_get_property_reply_t *reply)
{
std::vector<std::string> ret;
if (!reply) {
return ret;
}
if (reply->format != 8) {
return ret;
}
// 字符串拆分
uint32_t start = 0;
for (uint32_t i=0; i < reply->value_len; i++) {
if (reply->pad0[i] == 0) {
char data[12] = {0};
int count = 0;
for (uint32_t j=start; j < i; j++)
data[count++] = char(reply->pad0[j]);
data[count] = 0;
ret.push_back(data);
}
}
return ret;
}
XWindow XCBUtils::getRootWindow()
{
XWindow rootWindow = 0;
/* Get the first screen */
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(m_connect)).data;
if (screen) {
rootWindow = screen->root;
}
std::cout << "getRootWinodw: " << rootWindow << std::endl;
return rootWindow;
}
void XCBUtils::registerEvents(XWindow xid, uint32_t eventMask)
{
uint32_t value[1] = {eventMask};
xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(m_connect,
xid,
XCB_CW_EVENT_MASK,
&value);
flush();
xcb_generic_error_t *error = xcb_request_check(m_connect, cookie);
if (error != nullptr) {
std::cout << "window " << xid << "registerEvents error" << std::endl;
}
}
AtomCache::AtomCache()
{
}
XCBAtom AtomCache::getVal(std::string name)
{
XCBAtom atom = ATOMNONE;
auto search = m_atoms.find(name);
if (search != m_atoms.end()) {
atom = search->second;
}
return atom;
}
std::string AtomCache::getName(XCBAtom atom)
{
std::string ret;
auto search = m_atomNames.find(atom);
if (search != m_atomNames.end()) {
ret = search->second;
}
return ret;
}
void AtomCache::store(std::string name, XCBAtom value)
{
m_atoms[name] = value;
m_atomNames[value] = name;
}