summaryrefslogtreecommitdiff
path: root/src/plugins/platforms/xcb/qxcbconnection_basic.h
blob: 2efffd633c9debe9afb9f698efeaa5003195dfa1 (plain)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:COMM$
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** $QT_END_LICENSE$
**
**
**
**
**
**
**
**
**
**
**
**
**
**
**
**
**
**
**
****************************************************************************/
#ifndef QXCBBASICCONNECTION_H
#define QXCBBASICCONNECTION_H

#include "qxcbatom.h"
#include "qxcbexport.h"

#include <QtCore/QPair>
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QLoggingCategory>
#include <QtGui/private/qtguiglobal_p.h>

#include <xcb/xcb.h>

#include <memory>

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(lcQpaXcb)

class Q_XCB_EXPORT QXcbBasicConnection : public QObject
{
    Q_OBJECT
public:
    QXcbBasicConnection(const char *displayName);
    ~QXcbBasicConnection();

#if QT_CONFIG(xcb_xlib)
    void *xlib_display() const { return m_xlibDisplay; }
#endif
    const char *displayName() const { return m_displayName.constData(); }
    int primaryScreenNumber() const { return m_primaryScreenNumber; }
    xcb_connection_t *xcb_connection() const { return m_xcbConnection; }
    bool isConnected() const {
        return m_xcbConnection && !xcb_connection_has_error(m_xcbConnection);
    }
    const xcb_setup_t *setup() const { return m_setup; }

    size_t maxRequestDataBytes(size_t requestSize) const;

    inline xcb_atom_t atom(QXcbAtom::Atom qatom) const { return m_xcbAtom.atom(qatom); }
    QXcbAtom::Atom qatom(xcb_atom_t atom) const { return m_xcbAtom.qatom(atom); }
    xcb_atom_t internAtom(const char *name);
    QByteArray atomName(xcb_atom_t atom);

    bool hasXFixes() const { return m_hasXFixes; }
    bool hasXShape() const { return m_hasXhape; }
    bool hasXRandr() const { return m_hasXRandr; }
    bool hasInputShape() const { return m_hasInputShape; }
    bool hasXKB() const { return m_hasXkb; }
    bool hasXRender(int major = -1, int minor = -1) const {
        if (m_hasXRender && major != -1 && minor != -1)
            return m_xrenderVersion >= qMakePair(major, minor);

        return m_hasXRender;
    }
    bool hasXInput2() const { return m_xi2Enabled; }
    bool hasShm() const { return m_hasShm; }
    bool hasShmFd() const { return m_hasShmFd; }
    bool hasXSync() const { return m_hasXSync; }
    bool hasXinerama() const { return m_hasXinerama; }
    bool hasBigRequest() const;

    bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
    bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
    bool isXIEvent(xcb_generic_event_t *event) const;
    bool isXIType(xcb_generic_event_t *event, uint16_t type) const;

    bool isXFixesType(uint responseType, int eventType) const;
    bool isXRandrType(uint responseType, int eventType) const;
    bool isXkbType(uint responseType) const; // https://bugs.freedesktop.org/show_bug.cgi?id=51295

protected:
    void initializeShm();
    void initializeXFixes();
    void initializeXRender();
    void initializeXRandr();
    void initializeXinerama();
    void initializeXShape();
    void initializeXKB();
    void initializeXSync();
    void initializeXInput2();

private:
#if QT_CONFIG(xcb_xlib)
    void *m_xlibDisplay = nullptr;
#endif
    QByteArray m_displayName;
    xcb_connection_t *m_xcbConnection = nullptr;
    int m_primaryScreenNumber = 0;
    const xcb_setup_t *m_setup = nullptr;
    QXcbAtom m_xcbAtom;

    bool m_hasXFixes = false;
    bool m_hasXinerama = false;
    bool m_hasXhape = false;
    bool m_hasInputShape;
    bool m_hasXRandr = false;
    bool m_hasXkb = false;
    bool m_hasXRender = false;
    bool m_hasShm = false;
    bool m_hasShmFd = false;
    bool m_hasXSync = false;

    QPair<int, int> m_xrenderVersion;

    bool m_xi2Enabled = false;
    int m_xi2Minor = -1;
    int m_xiOpCode = -1;
    uint32_t m_xinputFirstEvent = 0;

    uint32_t m_xfixesFirstEvent = 0;
    uint32_t m_xrandrFirstEvent = 0;
    uint32_t m_xkbFirstEvent = 0;

    uint32_t m_maximumRequestLength = 0;
};

#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection

struct QStdFreeDeleter {
    void operator()(void *p) const noexcept { return std::free(p); }
};

#define Q_XCB_REPLY(call, ...) \
    std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
        call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr) \
    )

#define Q_XCB_REPLY_UNCHECKED(call, ...) \
    std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
        call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr) \
    )

QT_END_NAMESPACE

#endif // QXCBBASICCONNECTION_H