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 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | QXcbUnixEventDispatcher::QXcbUnixEventDispatcher(QXcbConnection *connection, QObject *parent) |
13 | : QEventDispatcherUNIX(parent) |
14 | , m_connection(connection) |
15 | { |
16 | } |
17 | |
18 | QXcbUnixEventDispatcher::~QXcbUnixEventDispatcher() |
19 | { |
20 | } |
21 | |
22 | bool 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) |
31 | struct XcbEventSource |
32 | { |
33 | GSource source; |
34 | QXcbGlibEventDispatcher *dispatcher; |
35 | QXcbGlibEventDispatcherPrivate *dispatcher_p; |
36 | QXcbConnection *connection = nullptr; |
37 | }; |
38 | |
39 | static 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 | |
46 | static gboolean xcbSourceCheck(GSource *source) |
47 | { |
48 | return xcbSourcePrepare(source, timeout: nullptr); |
49 | } |
50 | |
51 | static 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 | |
61 | QXcbGlibEventDispatcher::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 | |
83 | QXcbGlibEventDispatcherPrivate::QXcbGlibEventDispatcherPrivate() |
84 | { |
85 | } |
86 | |
87 | QXcbGlibEventDispatcher::~QXcbGlibEventDispatcher() |
88 | { |
89 | g_source_destroy(source: &m_xcbEventSource->source); |
90 | g_source_unref(source: &m_xcbEventSource->source); |
91 | } |
92 | |
93 | bool 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 | |
101 | QAbstractEventDispatcher *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 | |
115 | QT_END_NAMESPACE |
116 | |
117 | #include "moc_qxcbeventdispatcher.cpp" |
118 | |