summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2017-07-26 14:54:23 +0200
committerGatis Paeglis <gatis.paeglis@qt.io>2017-08-29 14:18:29 +0000
commitec2c0f4db6350a304dcf901b9adbadc895864c14 (patch)
treedb8c6df6b3143b67f18feeab78a6d2cccd92b8f1 /src
parent9749c5085dc21d2064177aa748f3a9395592a7cf (diff)
downloadqtx11extras-ec2c0f4db6350a304dcf901b9adbadc895864c14.tar.gz
[ChangeLog][QX11Info] Added new API to peek into the XCB event queue - peekEventQueue(). This enables porting certain Qt4-based applications to Qt5 (those using Xlib's event handling functions to peek into the X11 event queue). In Qt5 we set XCB to be the owner of the X11 event queue with XSetEventQueueOwner(dpy, XCBOwnsEventQueue), which means that only XCB event handling functions can be used to read events from the X server. XCB does not have an equivalent for Xlib's peeker API. For filtering out unwanted native events Qt5 provides QAbstractNativeEventFilter::nativeEventFilter(), but there isn't any API in Qt to just *peek* into the queue while the GUI thread is busy processing a long task. The peekEventQueue() function adds this capability via QX11Info. Manual and auto test included. Task-number: QTBUG-50358 Change-Id: Id31f797f7ff76d011ad7a55a9b6c13756aaaca60 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/x11extras/qx11info_x11.cpp158
-rw-r--r--src/x11extras/qx11info_x11.h17
2 files changed, 174 insertions, 1 deletions
diff --git a/src/x11extras/qx11info_x11.cpp b/src/x11extras/qx11info_x11.cpp
index 31bc405..e64ba9c 100644
--- a/src/x11extras/qx11info_x11.cpp
+++ b/src/x11extras/qx11info_x11.cpp
@@ -403,4 +403,162 @@ bool QX11Info::isCompositingManagerRunning(int screen)
return native->nativeResourceForScreen(QByteArray("compositingEnabled"), scr);
}
+/*!
+ Returns a new peeker id or -1 if some interal error has occurred.
+ Each peeker id is associated with an index in the buffered native
+ event queue.
+
+ For more details see QX11Info::PeekOption and peekEventQueue().
+
+ \sa peekEventQueue(), removePeekerId()
+ \since 5.10
+*/
+qint32 QX11Info::generatePeekerId()
+{
+ if (!qApp)
+ return -1;
+ QPlatformNativeInterface *native = qApp->platformNativeInterface();
+ if (!native)
+ return -1;
+
+ typedef qint32 (*GeneratePeekerIdFunc)(void);
+ GeneratePeekerIdFunc generatepeekerid = reinterpret_cast<GeneratePeekerIdFunc>(
+ native->nativeResourceFunctionForIntegration("generatepeekerid"));
+ if (!generatepeekerid) {
+ qWarning("Internal error: QPA plugin doesn't implement generatePeekerId");
+ return -1;
+ }
+
+ return generatepeekerid();
+}
+
+/*!
+ Removes \a peekerId, which was earlier obtained via generatePeekerId().
+
+ Returns \c true on success or \c false if unknown peeker id was
+ provided or some interal error has occurred.
+
+ \sa generatePeekerId()
+ \since 5.10
+*/
+bool QX11Info::removePeekerId(qint32 peekerId)
+{
+ if (!qApp)
+ return false;
+ QPlatformNativeInterface *native = qApp->platformNativeInterface();
+ if (!native)
+ return false;
+
+ typedef bool (*RemovePeekerIdFunc)(qint32);
+ RemovePeekerIdFunc removePeekerId = reinterpret_cast<RemovePeekerIdFunc>(
+ native->nativeResourceFunctionForIntegration("removepeekerid"));
+ if (!removePeekerId) {
+ qWarning("Internal error: QPA plugin doesn't implement removePeekerId");
+ return false;
+ }
+
+ return removePeekerId(peekerId);
+}
+
+/*!
+ \enum QX11Info::PeekOption
+ \brief An enum to tune the behavior of QX11Info::peekEventQueue().
+
+ \value PeekDefault
+ Peek from the beginning of the buffered native event queue. A peeker
+ id is optional with PeekDefault. If a peeker id is provided to
+ peekEventQueue() when using PeekDefault, then peeking starts from
+ the beginning of the queue, not from the cached index; thus, this
+ can be used to manually reset a cached index to peek from the start
+ of the queue. When this operation completes, the associated index
+ will be updated to the new position in the queue.
+
+ \value PeekFromCachedIndex
+ QX11Info::peekEventQueue() can optimize the peeking algorithm by
+ skipping events that it already has seen in earlier calls to
+ peekEventQueue(). When control returns to the main event loop,
+ which causes the buffered native event queue to be flushed to Qt's
+ event queue, the cached indices are marked invalid and will be
+ reset on the next access. The same is true if the program
+ explicitly flushes the buffered native event queue by
+ QCoreApplication::processEvents().
+
+ \since 5.10
+*/
+
+/*!
+ \typedef QX11Info::PeekerCallback
+ Typedef for a pointer to a function with the following signature:
+
+ \code
+ bool (*PeekerCallback)(xcb_generic_event_t *event, void *peekerData);
+ \endcode
+
+ The \a event is a native XCB event.
+ The \a peekerData is a pointer to data, passed in via peekEventQueue().
+
+ Return \c true from this function to stop examining the buffered
+ native event queue or \c false to continue.
+
+ \note A non-capturing lambda can serve as a PeekerCallback.
+ \since 5.10
+*/
+
+/*!
+ \brief Peek into the buffered XCB event queue.
+
+ You can call peekEventQueue() periodically, when your program is busy
+ performing a long-running operation, to peek into the buffered native
+ event queue. The more time the long-running operation blocks the
+ program from returning control to the main event loop, the more
+ events will accumulate in the buffered XCB event queue. Once control
+ returns to the main event loop these events will be flushed to Qt's
+ event queue, which is a separate event queue from the queue this
+ function is peeking into.
+
+ \note It is usually better to run CPU-intensive operations in a
+ non-GUI thread, instead of blocking the main event loop.
+
+ The buffered XCB event queue is populated from a non-GUI thread and
+ therefore might be ahead of the current GUI state. To handle native
+ events as they are processed by the GUI thread, see
+ QAbstractNativeEventFilter::nativeEventFilter().
+
+ The \a peeker is a callback function as documented in PeekerCallback.
+ The \a peekerData can be used to pass in arbitrary data to the \a
+ peeker callback.
+ The \a option is an enum that tunes the behavior of peekEventQueue().
+ The \a peekerId is used to track an index in the queue, for more
+ details see QX11Info::PeekOption. There can be several indices,
+ each tracked individually by a peeker id obtained via generatePeekerId().
+
+ This function returns \c true when the peeker has stopped the event
+ proccesing by returning \c true from the callback. If there were no
+ events in the buffered native event queue to peek at or all the
+ events have been processed by the peeker, this function returns \c
+ false.
+
+ \sa generatePeekerId(), QAbstractNativeEventFilter::nativeEventFilter()
+ \since 5.10
+*/
+bool QX11Info::peekEventQueue(PeekerCallback peeker, void *peekerData, PeekOptions option,
+ qint32 peekerId)
+{
+ if (!peeker || !qApp)
+ return false;
+ QPlatformNativeInterface *native = qApp->platformNativeInterface();
+ if (!native)
+ return false;
+
+ typedef bool (*PeekEventQueueFunc)(PeekerCallback, void *, PeekOptions, qint32);
+ PeekEventQueueFunc peekeventqueue = reinterpret_cast<PeekEventQueueFunc>(
+ native->nativeResourceFunctionForIntegration("peekeventqueue"));
+ if (!peekeventqueue) {
+ qWarning("Internal error: QPA plugin doesn't implement peekEventQueue");
+ return false;
+ }
+
+ return peekeventqueue(peeker, peekerData, option, peekerId);
+}
+
QT_END_NAMESPACE
diff --git a/src/x11extras/qx11info_x11.h b/src/x11extras/qx11info_x11.h
index ab72686..c0bfbf8 100644
--- a/src/x11extras/qx11info_x11.h
+++ b/src/x11extras/qx11info_x11.h
@@ -43,14 +43,21 @@
#include <QtCore/qnamespace.h>
#include "QtX11Extras/qtx11extrasglobal.h"
+#include <xcb/xcb.h>
+
typedef struct _XDisplay Display;
-struct xcb_connection_t;
QT_BEGIN_NAMESPACE
class Q_X11EXTRAS_EXPORT QX11Info
{
public:
+ enum PeekOption {
+ PeekDefault = 0,
+ PeekFromCachedIndex = 1
+ };
+ Q_DECLARE_FLAGS(PeekOptions, PeekOption)
+
static bool isPlatformX11();
static int appDpiX(int screen=-1);
@@ -75,10 +82,18 @@ public:
static bool isCompositingManagerRunning(int screen = -1);
+ static qint32 generatePeekerId();
+ static bool removePeekerId(qint32 peekerId);
+ typedef bool (*PeekerCallback)(xcb_generic_event_t *event, void *peekerData);
+ static bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
+ PeekOptions option = PeekDefault, qint32 peekerId = -1);
+
private:
QX11Info();
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QX11Info::PeekOptions)
+
QT_END_NAMESPACE
#endif // QX11INFO_X11_H