Skip to content

Commit

Permalink
Add ::peekEventQueue() API. (#1) (#1)
Browse files Browse the repository at this point in the history
Patch Qt5.6.1 for Maya. qtc-wip-add-peekeventqueue-api.patch.

From 785ec3bacfd4bf2c4b36ad21819816aea1345874 Mon Sep 17 00:00:00 2001
From: Gatis Paeglis <gatis.paeglis@theqtcompany.com>
Date: Mon, 27 Jul 2015 15:31:30 +0200
Subject: [PATCH] Add ::peekEventQueue() API

[ChangeLog][QX11Info] New API to peek into the XCB
event queue ::peekEventQueue(). This enables porting
certain Qt4 based applications to Qt5 - applications
that use Xlib's event handling functions to directly
access the X11 even queue.

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.

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 behavior to QX11Info.

Manual test included.

Task-number: QTBUG-50358
Change-Id: Id31f797f7ff76d011ad7a55a9b6c13756aaaca60
  • Loading branch information
zhihaoadsk committed Feb 24, 2017
1 parent d86b590 commit c6c59d5
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/x11extras/doc/qtx11extras.qdocconf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ qhp.QtX11Extras.subprojects.classes.indexTitle = Qt X11 Extras C++ Classes
qhp.QtX11Extras.subprojects.classes.selectors = class fake:headerfile
qhp.QtX11Extras.subprojects.classes.sortPages = true

depends += qtcore qtwidgets qtdoc qmake
depends += qtcore qtwidgets qtdoc qmake qtplatformheaders

headerdirs += ..

Expand Down
32 changes: 32 additions & 0 deletions src/x11extras/qx11info_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,4 +395,36 @@ bool QX11Info::isCompositingManagerRunning(int screen)
return native->nativeResourceForScreen(QByteArray("compositingEnabled"), scr);
}

/*!
This function can be used to peek into the XCB event queue.
You can call peekEventQueue() periodically when your program is busy performing
a long operation (for example, copying a file or performing a long-running
paint operation) to check if some other action should be performed instead.
The \a peeker object needs to implement the QXcbAbstractEventPeeker interface.
The \a option is an enum that alters the default behavior of peekEventQueue(),
see QXcbAbstractEventPeeker::PeekOption.
\since 5.7
*/

void QX11Info::peekEventQueue(QXcbAbstractEventPeeker *peeker, QXcbAbstractEventPeeker::PeekOption option)
{
if (!peeker || !qApp)
return;
QPlatformNativeInterface *native = qApp->platformNativeInterface();
if (!native)
return;

typedef void (*PeekEventQueueFunc)(QXcbAbstractEventPeeker *peeker, QXcbAbstractEventPeeker::PeekOption option);
PeekEventQueueFunc func = reinterpret_cast<PeekEventQueueFunc>(native->nativeResourceFunctionForIntegration("peekeventqueue"));
if (!func) {
qWarning("Internal error: QPA plugin doesn't implement peekEventQueue");
return;
}

func(peeker, option);
}

QT_END_NAMESPACE
4 changes: 4 additions & 0 deletions src/x11extras/qx11info_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#define QX11INFO_X11_H

#include <QtCore/qnamespace.h>
#include <QtPlatformHeaders/qxcbabstracteventpeeker.h>

#include "QtX11Extras/qtx11extrasglobal.h"

typedef struct _XDisplay Display;
Expand Down Expand Up @@ -68,6 +70,8 @@ class Q_X11EXTRAS_EXPORT QX11Info
static xcb_connection_t *connection();

static bool isCompositingManagerRunning(int screen = -1);
static void peekEventQueue(QXcbAbstractEventPeeker *peeker,
QXcbAbstractEventPeeker::PeekOption option = QXcbAbstractEventPeeker::PeekDefault);

private:
QX11Info();
Expand Down
3 changes: 3 additions & 0 deletions tests/manual/manual.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
TEMPLATE = subdirs

SUBDIRS = peeker
111 changes: 111 additions & 0 deletions tests/manual/peeker/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QPoint>
#include <QtCore/QRect>
#include <QtCore/QThread>
#include <QtGui/QPixmap>
#include <QtGui/QPainter>
#include <QtGui/QRegion>
#include <QtGui/QBackingStore>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
#include <QtWidgets/QApplication>

#include <qx11info_x11.h>

class HeavyPainter : public QWidget, public QXcbAbstractEventPeeker
{
Q_OBJECT
public:
HeavyPainter() : m_stopTasks(false) {}

void setStopTasks(bool stop) { m_stopTasks = stop; }

protected:
void paintEvent(QPaintEvent* e)
{
Q_UNUSED(e)
m_buffer = QPixmap(width(), height());
QPainter p(&m_buffer);

for (int i = 0; !m_stopTasks; ++i)
{
// long operation
p.fillRect(QRect(0, 0, width(), height()), i & 1 ? Qt::green : Qt::gray);
p.drawText(QPoint(10,10), "Press any key to exit");
QPainter p(this);
QPoint point = mapTo(window(), QPoint(0,0));
QRegion region(point.x(), point.y(), width(), height());

QBackingStore *bs = backingStore();
bs->beginPaint(region);
p.drawPixmap(0,0, m_buffer);

bs->endPaint();
bs->flush(region, windowHandle());

QThread::msleep(300);
QX11Info::peekEventQueue(this);
}

exit(0);
}

bool peekEventQueue(xcb_generic_event_t *event)
{
uint responseType = event->response_type & ~0x80;
if (responseType == XCB_KEY_PRESS) {
setStopTasks(true);
return true;
}

return false;
}

private:
bool m_stopTasks;
QPixmap m_buffer;
};

int main(int argc, char** argv)
{
QApplication app(argc, argv);

QWidget win;
win.setLayout(new QVBoxLayout);

QWidget *painter = new HeavyPainter;
win.layout()->addWidget(painter);

win.setGeometry(100,100,300,300);
win.show();

return app.exec();
}

#include "main.moc"
8 changes: 8 additions & 0 deletions tests/manual/peeker/peeker.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
QT += core gui widgets x11extras

LIBS += -lxcb

TARGET = peeker
TEMPLATE = app

SOURCES += main.cpp
2 changes: 1 addition & 1 deletion tests/tests.pro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TEMPLATE = subdirs

contains(QT_CONFIG, xcb) {
SUBDIRS += auto
SUBDIRS += auto manual
}

0 comments on commit c6c59d5

Please sign in to comment.