cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
139 lines
3.8 KiB
C++
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
|