File: nettesthelper.h

package info (click to toggle)
kf6-kwindowsystem 6.13.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 22,568 kB
  • sloc: cpp: 18,356; ansic: 35; makefile: 11; sh: 1
file content (138 lines) | stat: -rw-r--r-- 3,844 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
    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