donghualin bb3473e74a fix: 修复任务栏在智能隐藏模式下窗口拖动到任务栏下方没有隐藏的问题
1.计算窗口的位置和大小的时候,调用的接口获取到的数据不正确,已完善从上游xcb相关的接口获取其他相关的位置等数据,重新计算得到正确的窗口信息
2.松开鼠标的时候没有激活定时器处理,已增加松开鼠标后,对当前活动窗口的处理

Log:
Influence: 任务栏设置为智能隐藏,在窗口移动到任务栏下方或者移出来,观察隐藏状态是否正确
Bug: https://pms.uniontech.com/bug-view-154513.html
Change-Id: I2bcc4c0d922349a6c98636caab03bdf1a108964c
2022-10-14 02:00:29 +00:00

739 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.

/*
* Copyright (C) 2021 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "xcbutils.h"
#include <iostream>
#include <cstring>
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);
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply (m_connect,
cookie,
nullptr);
if (reply) {
m_atomCache.store(name, reply->atom);
ret = reply->atom;
free(reply);
}
}
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);
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(m_connect,
cookie,
nullptr);
if (reply) {
char *name = xcb_get_atom_name_name(reply);
if (name) {
m_atomCache.store(name, atom);
ret = name;
}
free(reply);
}
}
return ret;
}
Geometry XCBUtils::getWindowGeometry(XWindow xid)
{
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xcb_drawable_t(xid));
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(m_connect, cookie, nullptr);
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;
free(reply);
const xcb_setup_t *xcbSetup = xcb_get_setup(m_connect);
if (!xcbSetup)
return Geometry();
xcb_screen_iterator_t xcbScreenIterator = xcb_setup_roots_iterator(xcbSetup);
xcb_translate_coordinates_reply_t *translateReply =
xcb_translate_coordinates_reply(m_connect,
xcb_translate_coordinates(m_connect, xid, xcbScreenIterator.data->root, 0, 0),
nullptr);
if (translateReply) {
ret.x = translateReply->dst_x;
ret.y = translateReply->dst_y;
free(translateReply);
}
XWindow dWin = getDecorativeWindow(xid);
reply = xcb_get_geometry_reply(m_connect, xcb_get_geometry(m_connect, xcb_drawable_t(dWin)), nullptr);
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;
}
}
free(reply);
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);
xcb_query_tree_reply_t *reply = xcb_query_tree_reply(m_connect, cookie, nullptr);
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);
xcb_get_property_reply_t *reply = xcb_get_property_reply(m_connect, cookie, nullptr);
if (!reply || reply->format == 0) {
if (reply)
free(reply);
perp = getAtom("_GTK_FRAME_EXTENTS");
cookie = xcb_get_property(m_connect, false, xid, perp, XCB_ATOM_CARDINAL, 0, 4);
reply = xcb_get_property_reply(m_connect, cookie, nullptr);
if (!reply)
return WindowFrameExtents();
}
if (reply->format != 32 || reply->value_len != 4) {
free(reply);
return WindowFrameExtents();
}
uint32_t *data = static_cast<uint32_t *>(xcb_get_property_value(reply));
free(reply);
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);
// 释放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)
{
uint32_t ret = 0;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_pid(&m_ewmh, xid);
if (!xcb_ewmh_get_wm_pid_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << xid << " getWMPid error" << std::endl;
}
return ret;
}
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;
}
std::vector<WMIcon> XCBUtils::getWMIcon(XWindow xid)
{
std::vector<WMIcon> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon(&m_ewmh, xid);
xcb_ewmh_get_wm_icon_reply_t reply;
if (xcb_ewmh_get_wm_icon_reply(&m_ewmh, cookie, &reply, nullptr)) {
xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply);
auto fcn = [](xcb_ewmh_wm_icon_iterator_t it) {
std::vector<BYTE> ret;
// data数据是按行从左至右从上至下排列
uint32_t *data = it.data;
if (!data) {
return ret;
}
// 根据宽高获取每个位置的数据每行前有两个位置offset
int area = it.width * it.height;
for (int i = 0; i < (2 + area) * 4; i++, data++) {
ret.push_back(*data);
}
return ret;
};
ret.push_back({iter.width, iter.height, fcn(iter)});
// 获取不同size图标数据
while (iter.rem >= 1) {
xcb_ewmh_get_wm_icon_next(&iter);
ret.push_back({iter.width, iter.height, fcn(iter)});
}
xcb_ewmh_get_wm_icon_reply_wipe(&reply); // clear
}
return ret;
}
XWindow XCBUtils::getWMClientLeader(XWindow xid)
{
XWindow ret;
XCBAtom atom = getAtom("WM_CLIENT_LEADER");
void *value = getPropertyValue(xid, atom, XCB_ATOM_INTEGER);
std::cout << "getWMClientLeader:" << (char*)value << std::endl;
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);
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));
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;
}