Files
RedBear-OS/local/recipes/kde/kf6-kwindowsystem/source/autotests/nettesthelper.h
T
2026-04-14 10:51:06 +01:00

139 lines
3.8 KiB
C++

/*
SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef NETTESTHELPER_H
#define NETTESTHELPER_H
#include <QByteArray>
#include <memory>
#include <xcb/xcb.h>
#include "cptr_p.h"
namespace KXUtils
{
/**
* @brief Small helper class to fetch an intern atom through XCB.
*
* This class allows to request an intern atom and delay the retrieval of the reply
* till it is needed. In case the reply is never retrieved the reply gets discarded
* in the dtor. So there is no need to keep track manually about which atoms have been
* retrieved.
*
* This class can be used as a drop-in replacement for everywhere where a xcb_atom_t is
* needed as it implements the cast operator. The first time this operator is invoked it
* will retrieve the reply. If the xcb request failed the value is @c XCB_ATOM_NONE, which
* can be used to check whether the returned value is valid.
*
* This class has two modes of operations: a direct one which performs the request directly
* during construction, and an indirect one which needs an explicit call to {@link fetch}.
*
* @code
* Atom direct(QX11Info::connection(), QByteArrayLiteral("myAtomName"));
* Atom indirect(QByteArrayLiteral("myAtomName"));
* indirect.setConnection(QX11Info::connection());
* indirect.fetch();
*
* if (direct == XCB_ATOM_NONE) {
* qWarning() << "Request failed";
* }
* if (indirect == XCB_ATOM_NONE) {
* qWarning() << "Request failed";
* }
* @endcode
*/
class Atom
{
public:
explicit Atom(const QByteArray &name)
: m_connection(nullptr)
, m_retrieved(false)
, m_atom(XCB_ATOM_NONE)
, m_name(name)
{
m_cookie.sequence = 0;
}
explicit Atom(xcb_connection_t *c, const QByteArray &name, bool onlyIfExists = false)
: m_connection(c)
, m_retrieved(false)
, m_cookie(xcb_intern_atom_unchecked(m_connection, onlyIfExists, name.length(), name.constData()))
, m_atom(XCB_ATOM_NONE)
, m_name(name)
{
}
Atom() Q_DECL_EQ_DELETE;
Atom(const Atom &) Q_DECL_EQ_DELETE;
~Atom()
{
if (!m_retrieved && m_cookie.sequence) {
xcb_discard_reply(m_connection, m_cookie.sequence);
}
}
void setConnection(xcb_connection_t *c)
{
m_connection = c;
}
void fetch(bool onlyIfExists = false)
{
if (!m_connection) {
// set connection first!
return;
}
if (m_retrieved || m_cookie.sequence) {
// already fetched, don't fetch again
return;
}
m_cookie = xcb_intern_atom_unchecked(m_connection, onlyIfExists, m_name.length(), m_name.constData());
}
operator xcb_atom_t() const
{
(const_cast<Atom *>(this))->getReply();
return m_atom;
}
const QByteArray &name() const
{
return m_name;
}
private:
void getReply()
{
if (m_retrieved || !m_cookie.sequence) {
return;
}
UniqueCPointer<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(m_connection, m_cookie, nullptr));
if (reply) {
m_atom = reply->atom;
}
m_retrieved = true;
}
xcb_connection_t *m_connection;
bool m_retrieved;
xcb_intern_atom_cookie_t m_cookie;
xcb_atom_t m_atom;
QByteArray m_name;
};
inline xcb_window_t rootWindow(xcb_connection_t *c, int screen)
{
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(c));
for (xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(c)); it.rem; --screen, xcb_screen_next(&it)) {
if (screen == 0) {
return iter.data->root;
}
}
return XCB_WINDOW_NONE;
}
}
#endif