diff options
author | Gatis Paeglis <gatis.paeglis@qt.io> | 2017-07-26 14:54:23 +0200 |
---|---|---|
committer | Gatis Paeglis <gatis.paeglis@qt.io> | 2017-08-29 14:18:29 +0000 |
commit | ec2c0f4db6350a304dcf901b9adbadc895864c14 (patch) | |
tree | db8c6df6b3143b67f18feeab78a6d2cccd92b8f1 /src | |
parent | 9749c5085dc21d2064177aa748f3a9395592a7cf (diff) | |
download | qtx11extras-ec2c0f4db6350a304dcf901b9adbadc895864c14.tar.gz |
Add QX11Info::peekEventQueue() APIv5.10.0-beta3v5.10.0-beta2v5.10.0-beta1v5.10.0-alpha1
[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.cpp | 158 | ||||
-rw-r--r-- | src/x11extras/qx11info_x11.h | 17 |
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 |