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#include "qxcbeventdispatcher.h"
4#include "qxcbconnection.h"
5
6#include <QtCore/QCoreApplication>
7
8#include <qpa/qwindowsysteminterface.h>
9
10QT_BEGIN_NAMESPACE
11
12QXcbUnixEventDispatcher::QXcbUnixEventDispatcher(QXcbConnection *connection, QObject *parent)
13 : QEventDispatcherUNIX(parent)
14 , m_connection(connection)
15{
16}
17
18QXcbUnixEventDispatcher::~QXcbUnixEventDispatcher()
19{
20}
21
22bool QXcbUnixEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
23{
24 const bool didSendEvents = QEventDispatcherUNIX::processEvents(flags);
25 m_connection->processXcbEvents(flags);
26 // The following line should not be necessary after QTBUG-70095
27 return QWindowSystemInterface::sendWindowSystemEvents(flags) || didSendEvents;
28}
29
30#if QT_CONFIG(glib)
31struct XcbEventSource
32{
33 GSource source;
34 QXcbGlibEventDispatcher *dispatcher;
35 QXcbGlibEventDispatcherPrivate *dispatcher_p;
36 QXcbConnection *connection = nullptr;
37};
38
39static gboolean xcbSourcePrepare(GSource *source, gint *timeout)
40{
41 Q_UNUSED(timeout);
42 auto xcbEventSource = reinterpret_cast<XcbEventSource *>(source);
43 return xcbEventSource->dispatcher_p->wakeUpCalled;
44}
45
46static gboolean xcbSourceCheck(GSource *source)
47{
48 return xcbSourcePrepare(source, timeout: nullptr);
49}
50
51static gboolean xcbSourceDispatch(GSource *source, GSourceFunc, gpointer)
52{
53 auto xcbEventSource = reinterpret_cast<XcbEventSource *>(source);
54 QEventLoop::ProcessEventsFlags flags = xcbEventSource->dispatcher->flags();
55 xcbEventSource->connection->processXcbEvents(flags);
56 // The following line should not be necessary after QTBUG-70095
57 QWindowSystemInterface::sendWindowSystemEvents(flags);
58 return true;
59}
60
61QXcbGlibEventDispatcher::QXcbGlibEventDispatcher(QXcbConnection *connection, QObject *parent)
62 : QEventDispatcherGlib(*new QXcbGlibEventDispatcherPrivate(), parent)
63{
64 Q_D(QXcbGlibEventDispatcher);
65
66 m_xcbEventSourceFuncs.prepare = xcbSourcePrepare;
67 m_xcbEventSourceFuncs.check = xcbSourceCheck;
68 m_xcbEventSourceFuncs.dispatch = xcbSourceDispatch;
69 m_xcbEventSourceFuncs.finalize = nullptr;
70
71 GSource *source = g_source_new(source_funcs: &m_xcbEventSourceFuncs, struct_size: sizeof(XcbEventSource));
72 g_source_set_name(source, name: "[Qt] XcbEventSource");
73 m_xcbEventSource = reinterpret_cast<XcbEventSource *>(source);
74
75 m_xcbEventSource->dispatcher = this;
76 m_xcbEventSource->dispatcher_p = d_func();
77 m_xcbEventSource->connection = connection;
78
79 g_source_set_can_recurse(source: &m_xcbEventSource->source, can_recurse: true);
80 g_source_attach(source: &m_xcbEventSource->source, context: d->mainContext);
81}
82
83QXcbGlibEventDispatcherPrivate::QXcbGlibEventDispatcherPrivate()
84{
85}
86
87QXcbGlibEventDispatcher::~QXcbGlibEventDispatcher()
88{
89 g_source_destroy(source: &m_xcbEventSource->source);
90 g_source_unref(source: &m_xcbEventSource->source);
91}
92
93bool QXcbGlibEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
94{
95 m_flags = flags;
96 return QEventDispatcherGlib::processEvents(flags: m_flags);
97}
98
99#endif // QT_CONFIG(glib)
100
101QAbstractEventDispatcher *QXcbEventDispatcher::createEventDispatcher(QXcbConnection *connection)
102{
103#if QT_CONFIG(glib)
104 if (qEnvironmentVariableIsEmpty(varName: "QT_NO_GLIB") && QEventDispatcherGlib::versionSupported()) {
105 qCDebug(lcQpaXcb, "using glib dispatcher");
106 return new QXcbGlibEventDispatcher(connection);
107 } else
108#endif
109 {
110 qCDebug(lcQpaXcb, "using unix dispatcher");
111 return new QXcbUnixEventDispatcher(connection);
112 }
113}
114
115QT_END_NAMESPACE
116
117#include "moc_qxcbeventdispatcher.cpp"
118

source code of qtbase/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp