Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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// Qt-Security score:significant reason:default
4
5#pragma once
6
7#include <QtCore/QThread>
8#include <QtCore/QHash>
9#include <QtCore/QEventLoop>
10#include <QtCore/QList>
11#include <QtCore/QMutex>
12#include <QtCore/QWaitCondition>
13
14#include <xcb/xcb.h>
15
16#include <atomic>
17#include <limits>
18
19QT_BEGIN_NAMESPACE
20
21struct QXcbEventNode {
22 QXcbEventNode(xcb_generic_event_t *e = nullptr)
23 : event(e) { }
24
25 xcb_generic_event_t *event;
26 QXcbEventNode *next = nullptr;
27 bool fromHeap = false;
28};
29
30class QXcbConnection;
31class QAbstractEventDispatcher;
32
33class QXcbEventQueue : public QThread
34{
36public:
39
40 enum { PoolSize = 100 }; // 2.4 kB with 100 nodes
41
43 // See qx11info_x11.cpp in X11 Extras module.
45 // See qx11info_x11.cpp in X11 Extras module.
47 // Used by the event compression algorithms to determine if
48 // the currently processed event (which has been already dequeued)
49 // can be compressed. Returns from the QXcbEventQueue::peek()
50 // on the first match.
52 // Marks the event in the node as "nullptr". The actual
53 // node remains in the queue. The nodes are unlinked only
54 // by dequeueNode(). Returns from the QXcbEventQueue::peek()
55 // on the first match.
57 // Same as above, but continues to the next node in the
58 // queue. Repeats this until the flushed tailed node has
59 // been reached.
61 };
62 Q_DECLARE_FLAGS(PeekOptions, PeekOption)
63
64 void run() override;
65
66 bool isEmpty() const { return m_head == m_flushedTail && !m_head->event; }
67 xcb_generic_event_t *takeFirst(QEventLoop::ProcessEventsFlags flags);
68 xcb_generic_event_t *takeFirst();
70 void wakeUpDispatcher();
71
72 // ### peek() and peekEventQueue() could be unified. Note that peekEventQueue()
73 // is public API exposed via QX11Extras/QX11Info. PeekOption could be reworked to
74 // have values that can be OR-ed together.
75 template<typename Peeker>
76 xcb_generic_event_t *peek(Peeker &&peeker) {
77 return peek(PeekConsumeMatch, std::forward<Peeker>(peeker));
78 }
79 template<typename Peeker>
80 inline xcb_generic_event_t *peek(PeekOption config, Peeker &&peeker);
81
83 bool removePeekerId(qint32 peekerId);
84
85 using PeekerCallback = bool (*)(xcb_generic_event_t *event, void *peekerData);
86 bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
87 PeekOptions option = PeekDefault, qint32 peekerId = -1);
88
89 const QXcbEventNode *flushedTail() const { return m_flushedTail; }
90 void waitForNewEvents(const QXcbEventNode *sinceFlushedTail,
91 unsigned long time = (std::numeric_limits<unsigned long>::max)());
92
93private:
94 QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event);
95 void dequeueNode();
96
97 void sendCloseConnectionEvent() const;
98 bool isCloseConnectionEvent(const xcb_generic_event_t *event);
99
100 QXcbEventNode *m_head = nullptr;
101 QXcbEventNode *m_flushedTail = nullptr;
102 std::atomic<QXcbEventNode *> m_tail { nullptr };
103 std::atomic_uint m_nodesRestored { 0 };
104
105 QXcbConnection *m_connection = nullptr;
106 bool m_closeConnectionDetected = false;
107
108 uint m_freeNodes = PoolSize;
109 uint m_poolIndex = 0;
110
111 qint32 m_peekerIdSource = 0;
112 bool m_queueModified = false;
113 bool m_peekerIndexCacheDirty = false;
114 QHash<qint32, QXcbEventNode *> m_peekerToNode;
115
116 QList<xcb_generic_event_t *> m_inputEvents;
117
118 // debug stats
119 quint64 m_nodesOnHeap = 0;
120
121 QMutex m_newEventsMutex;
122 QWaitCondition m_newEventsCondition;
123};
124
125template<typename Peeker>
126xcb_generic_event_t *QXcbEventQueue::peek(PeekOption option, Peeker &&peeker)
127{
129 if (isEmpty())
130 return nullptr;
131
132 QXcbEventNode *node = m_head;
133 do {
134 xcb_generic_event_t *event = node->event;
135 if (event && peeker(event, event->response_type & ~0x80)) {
136 if (option == PeekConsumeMatch || option == PeekConsumeMatchAndContinue)
137 node->event = nullptr;
138
139 if (option != PeekConsumeMatchAndContinue)
140 return event;
141 }
142 if (node == m_flushedTail)
143 break;
144 node = node->next;
145 } while (true);
146
147 return nullptr;
148}
149
150QT_END_NAMESPACE
\inmodule QtSql
bool(*)(xcb_generic_event_t *event, void *peekerData) PeekerCallback
bool removePeekerId(qint32 peekerId)
qint32 generatePeekerId()
const QXcbEventNode * flushedTail() const
xcb_generic_event_t * peek(PeekOption config, Peeker &&peeker)
bool isEmpty() const
xcb_generic_event_t * takeFirst(QEventLoop::ProcessEventsFlags flags)
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)
bool isForeignWindow() const override
Definition qxcbwindow.h:273
void create() override
Definition qxcbwindow.h:276
QXcbForeignWindow(QWindow *window, WId nativeHandle)
QXcbConnection * connection() const
Definition qxcbobject.h:17
xcb_connection_t * xcb_connection() const
Definition qxcbobject.h:20
xcb_atom_t atom(QXcbAtom::Atom atom) const
Definition qxcbobject.h:19
void setConnection(QXcbConnection *connection)
Definition qxcbobject.h:16
QXcbObject(QXcbConnection *connection=nullptr)
Definition qxcbobject.h:14
QXcbWindow * window() const
QXcbSyncWindowRequest(QXcbWindow *w)
virtual void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *)
virtual void handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *)
virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource=Qt::MouseEventNotSynthesized)
virtual void handleButtonPressEvent(const xcb_button_press_event_t *)
virtual void handleEnterNotifyEvent(const xcb_enter_notify_event_t *)
virtual void handleMapNotifyEvent(const xcb_map_notify_event_t *)
virtual void handleClientMessageEvent(const xcb_client_message_event_t *)
virtual void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *)
virtual void handleXIEnterLeave(xcb_ge_event_t *)
virtual void handleMotionNotifyEvent(const xcb_motion_notify_event_t *)
virtual void handleLeaveNotifyEvent(const xcb_leave_notify_event_t *)
virtual void handleButtonReleaseEvent(const xcb_button_release_event_t *)
virtual void handleExposeEvent(const xcb_expose_event_t *)
virtual void handleFocusOutEvent(const xcb_focus_out_event_t *)
virtual void handleFocusInEvent(const xcb_focus_in_event_t *)
virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *)
virtual bool handleNativeEvent(xcb_generic_event_t *)
virtual QXcbWindow * toWindow()
QHash< xcb_window_t, QXcbWindowEventListener * > WindowMapper
#define Q_XCB_EXPORT
Definition qxcbexport.h:14
QList< xcb_rectangle_t > qRegionToXcbRectangleList(const QRegion &region)