Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qxcbeventqueue.h
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QXCBEVENTQUEUE_H
4#define QXCBEVENTQUEUE_H
5
6#include <QtCore/QThread>
7#include <QtCore/QHash>
8#include <QtCore/QEventLoop>
9#include <QtCore/QList>
10#include <QtCore/QMutex>
11#include <QtCore/QWaitCondition>
12
13#include <xcb/xcb.h>
14
15#include <atomic>
16#include <limits>
17
19
21 QXcbEventNode(xcb_generic_event_t *e = nullptr)
22 : event(e) { }
23
24 xcb_generic_event_t *event;
25 QXcbEventNode *next = nullptr;
26 bool fromHeap = false;
27};
28
29class QXcbConnection;
31
32class QXcbEventQueue : public QThread
33{
35public:
38
39 enum { PoolSize = 100 }; // 2.4 kB with 100 nodes
40
42 // See qx11info_x11.cpp in X11 Extras module.
44 // See qx11info_x11.cpp in X11 Extras module.
46 // Used by the event compression algorithms to determine if
47 // the currently processed event (which has been already dequeued)
48 // can be compressed. Returns from the QXcbEventQueue::peek()
49 // on the first match.
51 // Marks the event in the node as "nullptr". The actual
52 // node remains in the queue. The nodes are unlinked only
53 // by dequeueNode(). Returns from the QXcbEventQueue::peek()
54 // on the first match.
56 // Same as above, but continues to the next node in the
57 // queue. Repeats this until the flushed tailed node has
58 // been reached.
60 };
61 Q_DECLARE_FLAGS(PeekOptions, PeekOption)
62
63 void run() override;
64
65 bool isEmpty() const { return m_head == m_flushedTail && !m_head->event; }
66 xcb_generic_event_t *takeFirst(QEventLoop::ProcessEventsFlags flags);
67 xcb_generic_event_t *takeFirst();
69 void wakeUpDispatcher();
70
71 // ### peek() and peekEventQueue() could be unified. Note that peekEventQueue()
72 // is public API exposed via QX11Extras/QX11Info. PeekOption could be reworked to
73 // have values that can be OR-ed together.
74 template<typename Peeker>
75 xcb_generic_event_t *peek(Peeker &&peeker) {
76 return peek(PeekConsumeMatch, std::forward<Peeker>(peeker));
77 }
78 template<typename Peeker>
79 inline xcb_generic_event_t *peek(PeekOption config, Peeker &&peeker);
80
82 bool removePeekerId(qint32 peekerId);
83
84 using PeekerCallback = bool (*)(xcb_generic_event_t *event, void *peekerData);
85 bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
86 PeekOptions option = PeekDefault, qint32 peekerId = -1);
87
88 const QXcbEventNode *flushedTail() const { return m_flushedTail; }
89 void waitForNewEvents(const QXcbEventNode *sinceFlushedTail,
90 unsigned long time = (std::numeric_limits<unsigned long>::max)());
91
92private:
93 QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event);
94 void dequeueNode();
95
96 void sendCloseConnectionEvent() const;
97 bool isCloseConnectionEvent(const xcb_generic_event_t *event);
98
99 QXcbEventNode *m_head = nullptr;
100 QXcbEventNode *m_flushedTail = nullptr;
101 std::atomic<QXcbEventNode *> m_tail { nullptr };
102 std::atomic_uint m_nodesRestored { 0 };
103
104 QXcbConnection *m_connection = nullptr;
105 bool m_closeConnectionDetected = false;
106
107 uint m_freeNodes = PoolSize;
108 uint m_poolIndex = 0;
109
110 qint32 m_peekerIdSource = 0;
111 bool m_queueModified = false;
112 bool m_peekerIndexCacheDirty = false;
113 QHash<qint32, QXcbEventNode *> m_peekerToNode;
114
115 QList<xcb_generic_event_t *> m_inputEvents;
116
117 // debug stats
118 quint64 m_nodesOnHeap = 0;
119
120 QMutex m_newEventsMutex;
121 QWaitCondition m_newEventsCondition;
122};
123
124template<typename Peeker>
125xcb_generic_event_t *QXcbEventQueue::peek(PeekOption option, Peeker &&peeker)
126{
128 if (isEmpty())
129 return nullptr;
130
131 QXcbEventNode *node = m_head;
132 do {
133 xcb_generic_event_t *event = node->event;
134 if (event && peeker(event, event->response_type & ~0x80)) {
136 node->event = nullptr;
137
139 return event;
140 }
141 if (node == m_flushedTail)
142 break;
143 node = node->next;
144 } while (true);
145
146 return nullptr;
147}
148
150
151#endif
\inmodule QtCore
Definition qmutex.h:281
bool(*)(xcb_generic_event_t *event, void *peekerData) PeekerCallback
bool removePeekerId(qint32 peekerId)
qint32 generatePeekerId()
QXcbEventQueue(QXcbConnection *connection)
const QXcbEventNode * flushedTail() const
bool isEmpty() const
void run() override
xcb_generic_event_t * peek(Peeker &&peeker)
xcb_generic_event_t * takeFirst()
void waitForNewEvents(const QXcbEventNode *sinceFlushedTail, unsigned long time=(std::numeric_limits< unsigned long >::max)())
bool peekEventQueue(PeekerCallback peeker, void *peekerData=nullptr, PeekOptions option=PeekDefault, qint32 peekerId=-1)
Combined button and popup list for selecting options.
DBusConnection * connection
EGLConfig config
#define Q_DECLARE_FLAGS(Flags, Enum)
Definition qflags.h:174
GLbitfield flags
struct _cl_event * event
GLuint GLenum option
#define Q_OBJECT
int qint32
Definition qtypes.h:49
unsigned long long quint64
Definition qtypes.h:61
unsigned int uint
Definition qtypes.h:34
xcb_generic_event_t * event
QXcbEventNode * next
QXcbEventNode(xcb_generic_event_t *e=nullptr)