Provide public API for native event filtering, moved up from QPA.
The previous API was hard to use (global function, no type safety, manual chaining), and confusing (app vs dispatcher split only made sense on Windows). Installing and removing out of order would have the risk of setting back a dangling pointer (crash). Meanwhile QPA added type safety, and this new API models the QObject::installEventFilter API for ease of use. The virtual method is in a new interface, QAbstractNativeEventFilter. QPA was even calling the dispatcher event filter with QPA-private event classes, which made no sense (refactoring leftover from when the code was in the dispatcher). Now the QPA plugins trigger the qcoreapp event filters with the actual native events directly. Change-Id: Ie35e47c59c862383bcaf857b28d54f7c72547882 Reviewed-by: Marius Storm-Olsen <marius.storm-olsen@nokia.com>
This commit is contained in:
parent
981ea7a1aa
commit
1603ba2365
8
dist/changes-5.0.0
vendored
8
dist/changes-5.0.0
vendored
@ -389,6 +389,14 @@ QtCore
|
||||
* QEvent::AccessibilityPrepare, AccessibilityHelp and AccessibilityDescription removed:
|
||||
* The enum values simply didn't make sense in the first place and should simply be dropped.
|
||||
|
||||
* Filtering of native events (QCoreApplication::setEventFilter, as well as
|
||||
QApplication::x11EventFilter/macEventFilter/qwsEventFilter) have been replaced
|
||||
with QCoreApplication::installNativeEventFilter and removeNativeEventFilter,
|
||||
for an API much closer to QEvent filtering. Note that the native events that can be
|
||||
filtered this way depend on which QPA backend is chosen, at runtime. On X11, XEvents are
|
||||
not used anymore, and have been replaced with xcb_generic_event_t due to the switch to
|
||||
XCB, which requires porting the application code to XCB as well.
|
||||
|
||||
* [QTBUG-23529] QHash is now more resilient to a family of denial of service
|
||||
attacks exploiting algorithmic complexity, by supporting two-arguments overloads
|
||||
of the qHash() hashing function.
|
||||
|
@ -39,5 +39,16 @@
|
||||
****************************************************************************/
|
||||
|
||||
//! [0]
|
||||
bool myEventFilter(void *message);
|
||||
class MyXcbEventFilter : public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
|
||||
{
|
||||
if (eventType == "xcb_generic_event_t") {
|
||||
xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
|
||||
// ...
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//! [0]
|
@ -57,7 +57,7 @@ foreach (const QString &path, app.libraryPaths())
|
||||
|
||||
|
||||
//! [3]
|
||||
bool myEventFilter(void *message, long *result);
|
||||
|
||||
//! [3]
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
HEADERS += \
|
||||
kernel/qabstracteventdispatcher.h \
|
||||
kernel/qabstractnativeeventfilter.h \
|
||||
kernel/qbasictimer.h \
|
||||
kernel/qeventloop.h\
|
||||
kernel/qpointer.h \
|
||||
@ -42,6 +43,7 @@ HEADERS += \
|
||||
|
||||
SOURCES += \
|
||||
kernel/qabstracteventdispatcher.cpp \
|
||||
kernel/qabstractnativeeventfilter.cpp \
|
||||
kernel/qbasictimer.cpp \
|
||||
kernel/qeventloop.cpp \
|
||||
kernel/qcoreapplication.cpp \
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "qabstracteventdispatcher.h"
|
||||
#include "qabstracteventdispatcher_p.h"
|
||||
#include "qabstractnativeeventfilter.h"
|
||||
|
||||
#include "qthread.h"
|
||||
#include <private/qthread_p.h>
|
||||
@ -370,87 +371,96 @@ void QAbstractEventDispatcher::closingDown()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAbstractEventDispatcher::EventFilter
|
||||
Installs an event filter \a filterObj for all native event filters
|
||||
received by the application.
|
||||
|
||||
Typedef for a function with the signature
|
||||
The event filter \a filterObj receives events via its nativeEventFilter()
|
||||
function, which is called for all events received by all threads.
|
||||
|
||||
\snippet code/src_corelib_kernel_qabstracteventdispatcher.cpp 0
|
||||
|
||||
Note that the type of the \a message is platform dependent. The
|
||||
following table shows the \a {message}'s type on Windows, Mac, and
|
||||
X11. You can do a static cast to these types.
|
||||
|
||||
\table
|
||||
\header
|
||||
\li Platform
|
||||
\li type
|
||||
\row
|
||||
\li Windows
|
||||
\li MSG
|
||||
\row
|
||||
\li X11
|
||||
\li XEvent
|
||||
\row
|
||||
\li Mac
|
||||
\li NSEvent
|
||||
\endtable
|
||||
|
||||
|
||||
|
||||
\sa setEventFilter(), filterEvent()
|
||||
*/
|
||||
|
||||
/*!
|
||||
Replaces the event filter function for this
|
||||
QAbstractEventDispatcher with \a filter and returns the replaced
|
||||
event filter function. Only the current event filter function is
|
||||
called. If you want to use both filter functions, save the
|
||||
replaced EventFilter in a place where yours can call it.
|
||||
|
||||
The event filter function set here is called for all messages
|
||||
taken from the system event loop before the event is dispatched to
|
||||
the respective target, including the messages not meant for Qt
|
||||
objects.
|
||||
|
||||
The event filter function should return true if the message should
|
||||
The nativeEventFilter() function should return true if the event should
|
||||
be filtered, (i.e. stopped). It should return false to allow
|
||||
processing the message to continue.
|
||||
normal Qt processing to continue: the native event can then be translated
|
||||
into a QEvent and handled by the standard Qt \l{QEvent} {event} filtering,
|
||||
e.g. QObject::installEventFilter().
|
||||
|
||||
By default, no event filter function is set (i.e., this function
|
||||
returns a null EventFilter the first time it is called).
|
||||
If multiple event filters are installed, the filter that was installed last
|
||||
is activated first.
|
||||
|
||||
\note The filter function set here receives native messages,
|
||||
i.e. MSG or XEvent structs.
|
||||
|
||||
For maximum portability, you should always try to use QEvents
|
||||
and QObject::installEventFilter() whenever possible.
|
||||
|
||||
\sa QObject::installEventFilter()
|
||||
|
||||
\since 5.0
|
||||
*/
|
||||
QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter)
|
||||
void QAbstractEventDispatcher::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
|
||||
{
|
||||
Q_D(QAbstractEventDispatcher);
|
||||
EventFilter oldFilter = d->event_filter;
|
||||
d->event_filter = filter;
|
||||
return oldFilter;
|
||||
|
||||
// clean up unused items in the list
|
||||
d->eventFilters.removeAll(0);
|
||||
d->eventFilters.removeAll(filterObj);
|
||||
d->eventFilters.prepend(filterObj);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sends \a message through the event filter that was set by
|
||||
setEventFilter(). If no event filter has been set, this function
|
||||
returns false; otherwise, this function returns the result of the
|
||||
event filter function.
|
||||
Removes an event filter object \a obj from this object. The
|
||||
request is ignored if such an event filter has not been installed.
|
||||
|
||||
All event filters for this object are automatically removed when
|
||||
this object is destroyed.
|
||||
|
||||
It is always safe to remove an event filter, even during event
|
||||
filter activation (i.e. from the nativeEventFilter() function).
|
||||
|
||||
\sa installNativeEventFilter(), QAbstractNativeEventFilter
|
||||
\since 5.0
|
||||
*/
|
||||
void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)
|
||||
{
|
||||
Q_D(QAbstractEventDispatcher);
|
||||
for (int i = 0; i < d->eventFilters.count(); ++i) {
|
||||
if (d->eventFilters.at(i) == filterObj) {
|
||||
d->eventFilters[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sends \a message through the event filters that were set by
|
||||
installNativeEventFilter(). This function returns true as soon as an
|
||||
event filter returns true, and false otherwise to indicate that
|
||||
the processing of the event should continue.
|
||||
|
||||
Subclasses of QAbstractEventDispatcher \e must call this function
|
||||
for \e all messages received from the system to ensure
|
||||
compatibility with any extensions that may be used in the
|
||||
application.
|
||||
|
||||
Note that the type of \a message is platform dependent. See
|
||||
QAbstractEventDispatcher::EventFilter for details.
|
||||
Note that the type of \a message is platform dependent. See
|
||||
QAbstractNativeEventFilter for details.
|
||||
|
||||
\sa setEventFilter()
|
||||
\sa installNativeEventFilter()
|
||||
\since 5.0
|
||||
*/
|
||||
bool QAbstractEventDispatcher::filterEvent(void *message)
|
||||
bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
Q_D(QAbstractEventDispatcher);
|
||||
if (d->event_filter) {
|
||||
if (!d->eventFilters.isEmpty()) {
|
||||
// Raise the loopLevel so that deleteLater() calls in or triggered
|
||||
// by event_filter() will be processed from the main event loop.
|
||||
QScopedLoopLevelCounter loopLevelCounter(d->threadData);
|
||||
return d->event_filter(message);
|
||||
for (int i = 0; i < d->eventFilters.size(); ++i) {
|
||||
QAbstractNativeEventFilter *filter = d->eventFilters.at(i);
|
||||
if (!filter)
|
||||
continue;
|
||||
if (filter->nativeEventFilter(eventType, message, result))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ QT_BEGIN_HEADER
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
class QAbstractNativeEventFilter;
|
||||
class QAbstractEventDispatcherPrivate;
|
||||
class QSocketNotifier;
|
||||
|
||||
@ -111,9 +111,12 @@ public:
|
||||
virtual void startingUp();
|
||||
virtual void closingDown();
|
||||
|
||||
typedef bool(*EventFilter)(void *message);
|
||||
EventFilter setEventFilter(EventFilter filter);
|
||||
bool filterEvent(void *message);
|
||||
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj);
|
||||
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj);
|
||||
bool filterNativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||
#if QT_DEPRECATED_SINCE(5, 0)
|
||||
QT_DEPRECATED bool filterEvent(void *message) { return filterNativeEvent("", message, 0); }
|
||||
#endif
|
||||
|
||||
Q_SIGNALS:
|
||||
void aboutToBlock();
|
||||
|
@ -65,9 +65,9 @@ class Q_CORE_EXPORT QAbstractEventDispatcherPrivate : public QObjectPrivate
|
||||
Q_DECLARE_PUBLIC(QAbstractEventDispatcher)
|
||||
public:
|
||||
inline QAbstractEventDispatcherPrivate()
|
||||
: event_filter(0)
|
||||
{ }
|
||||
QAbstractEventDispatcher::EventFilter event_filter;
|
||||
|
||||
QList<QAbstractNativeEventFilter *> eventFilters;
|
||||
|
||||
static int allocateTimerId();
|
||||
static void releaseTimerId(int id);
|
||||
|
105
src/corelib/kernel/qabstractnativeeventfilter.cpp
Normal file
105
src/corelib/kernel/qabstractnativeeventfilter.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qabstractnativeeventfilter.h"
|
||||
#include "qabstracteventdispatcher.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QAbstractNativeEventFilter
|
||||
\since 5.0
|
||||
|
||||
\brief The QAbstractNativeEventFilter class provides an interface for receiving native
|
||||
events, such as MSG or XCB event structs.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Creates a native event filter.
|
||||
|
||||
By default this doesn't do anything. Remember to install it on the application
|
||||
object.
|
||||
*/
|
||||
QAbstractNativeEventFilter::QAbstractNativeEventFilter()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the native event filter.
|
||||
|
||||
This automatically removes it from the application.
|
||||
*/
|
||||
QAbstractNativeEventFilter::~QAbstractNativeEventFilter()
|
||||
{
|
||||
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
|
||||
if (eventDispatcher)
|
||||
eventDispatcher->removeNativeEventFilter(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
|
||||
This method is called for every native event.
|
||||
|
||||
\note The filter function here receives native messages,
|
||||
for example, MSG or XCB event structs.
|
||||
|
||||
It is called by the QPA platform plugin. On Windows, it is called by
|
||||
the event dispatcher.
|
||||
|
||||
The type of event \a eventType is specific to the platform plugin chosen at run-time,
|
||||
and can be used to cast \a message to the right type.
|
||||
|
||||
On X11, \a eventType is set to "xcb_generic_event_t", and the \a message can be casted
|
||||
to a xcb_generic_event_t pointer.
|
||||
|
||||
On Windows, \a eventType is set to "windows_generic_MSG" for messages sent to toplevel windows,
|
||||
and "windows_dispatcher_MSG" for system-wide messages such as messages from a registered hot key.
|
||||
In both cases, the \a message can be casted to a MSG pointer.
|
||||
The \a result pointer is only used on Windows, and corresponds to the LRESULT pointer.
|
||||
|
||||
On Mac, \a eventType is set to "mac_generic_NSEvent", and the \a message can be casted to an EventRef.
|
||||
|
||||
Example:
|
||||
\snippet code/src_corelib_kernel_qabstractnativeeventfilter.cpp 0
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
70
src/corelib/kernel/qabstractnativeeventfilter.h
Normal file
70
src/corelib/kernel/qabstractnativeeventfilter.h
Normal file
@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QABSTRACTNATIVEEVENTFILTER_H
|
||||
#define QABSTRACTNATIVEEVENTFILTER_H
|
||||
|
||||
#include <QtCore/qnamespace.h>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAbstractNativeEventFilterPrivate;
|
||||
|
||||
class Q_CORE_EXPORT QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
QAbstractNativeEventFilter();
|
||||
virtual ~QAbstractNativeEventFilter();
|
||||
|
||||
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) = 0;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QAbstractNativeEventFilter)
|
||||
QAbstractNativeEventFilterPrivate *d;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
||||
#endif /* QABSTRACTNATIVEEVENTFILTER_H */
|
@ -286,7 +286,6 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
|
||||
, origArgv(new char *[aargc])
|
||||
#endif
|
||||
, application_type(0)
|
||||
, eventFilter(0)
|
||||
, in_exec(false)
|
||||
, aboutToQuitEmitted(false)
|
||||
, threadData_clean(false)
|
||||
@ -765,7 +764,7 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
|
||||
do not change the focus widget.
|
||||
\endlist
|
||||
|
||||
\sa QObject::event(), installEventFilter()
|
||||
\sa QObject::event(), installNativeEventFilter()
|
||||
*/
|
||||
|
||||
bool QCoreApplication::notify(QObject *receiver, QEvent *event)
|
||||
@ -2140,80 +2139,94 @@ void QCoreApplication::removeLibraryPath(const QString &path)
|
||||
#endif //QT_NO_LIBRARY
|
||||
|
||||
/*!
|
||||
\typedef QCoreApplication::EventFilter
|
||||
Sends \a message through the event filters that were set by
|
||||
installNativeEventFilter(). This function returns true as soon as an
|
||||
event filter returns true, and false otherwise to indicate that
|
||||
the processing of the event should continue.
|
||||
|
||||
A function with the following signature that can be used as an
|
||||
event filter:
|
||||
Subclasses of QAbstractEventDispatcher \e must call this function
|
||||
for \e all messages received from the system to ensure
|
||||
compatibility with any extensions that may be used in the
|
||||
application.
|
||||
|
||||
\snippet code/src_corelib_kernel_qcoreapplication.cpp 3
|
||||
Note that the type of \a message is platform dependent. See
|
||||
QAbstractNativeEventFilter for details.
|
||||
|
||||
\sa setEventFilter()
|
||||
\sa installNativeEventFilter()
|
||||
\since 5.0
|
||||
|
||||
\internal
|
||||
This method only exists for the Windows event dispatcher to call the winEventFilter virtual.
|
||||
Every other platform can just use QAbstractNativeEventFilter::filterNativeEvent directly.
|
||||
*/
|
||||
bool QCoreApplication::filterNativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
if (result)
|
||||
*result = 0;
|
||||
#ifdef Q_OS_WIN
|
||||
if (winEventFilter(reinterpret_cast<MSG *>(message), result))
|
||||
return true;
|
||||
#endif
|
||||
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
|
||||
if (dispatcher)
|
||||
return dispatcher->filterNativeEvent(eventType, message, result);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn EventFilter QCoreApplication::setEventFilter(EventFilter filter)
|
||||
Installs an event filter \a filterObj for all native events
|
||||
received by the application in the main thread.
|
||||
|
||||
Replaces the event filter function for the QCoreApplication with
|
||||
\a filter and returns the pointer to the replaced event filter
|
||||
function. Only the current event filter function is called. If you
|
||||
want to use both filter functions, save the replaced EventFilter
|
||||
in a place where yours can call it.
|
||||
The event filter \a filterObj receives events via its nativeEventFilter()
|
||||
function, which is called for all native events received in the main thread.
|
||||
|
||||
The event filter function set here is called for all messages
|
||||
received by all threads meant for all Qt objects. It is \e not
|
||||
called for messages that are not meant for Qt objects.
|
||||
|
||||
The event filter function should return true if the message should
|
||||
The nativeEventFilter() function should return true if the event should
|
||||
be filtered, (i.e. stopped). It should return false to allow
|
||||
processing the message to continue.
|
||||
normal Qt processing to continue: the native event can then be translated
|
||||
into a QEvent and handled by the standard Qt \l{QEvent} {event} filtering,
|
||||
e.g. QObject::installEventFilter().
|
||||
|
||||
By default, no event filter function is set (i.e., this function
|
||||
returns a null EventFilter the first time it is called).
|
||||
If multiple event filters are installed, the filter that was
|
||||
installed last is activated first.
|
||||
|
||||
\note The filter function set here receives native messages,
|
||||
i.e. MSG or XEvent structs, that are going to Qt objects. It is
|
||||
called by QCoreApplication::filterEvent(). If the filter function
|
||||
returns false to indicate the message should be processed further,
|
||||
the native message can then be translated into a QEvent and
|
||||
handled by the standard Qt \l{QEvent} {event} filering, e.g.
|
||||
QObject::installEventFilter().
|
||||
i.e. MSG or XCB event structs.
|
||||
|
||||
\note The filter function set here is different form the filter
|
||||
function set via QAbstractEventDispatcher::setEventFilter(), which
|
||||
gets all messages received by its thread, even messages meant for
|
||||
objects that are not handled by Qt.
|
||||
For maximum portability, you should always try to use QEvents
|
||||
and QObject::installEventFilter() whenever possible.
|
||||
|
||||
\sa QObject::installEventFilter(), QAbstractEventDispatcher::setEventFilter()
|
||||
\sa QObject::installEventFilter()
|
||||
|
||||
\since 5.0
|
||||
*/
|
||||
QCoreApplication::EventFilter
|
||||
QCoreApplication::setEventFilter(QCoreApplication::EventFilter filter)
|
||||
void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
|
||||
{
|
||||
Q_D(QCoreApplication);
|
||||
EventFilter old = d->eventFilter;
|
||||
d->eventFilter = filter;
|
||||
return old;
|
||||
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread);
|
||||
if (!filterObj || !eventDispatcher)
|
||||
return;
|
||||
eventDispatcher->installNativeEventFilter(filterObj);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sends \a message through the event filter that was set by
|
||||
setEventFilter(). If no event filter has been set, this function
|
||||
returns false; otherwise, this function returns the result of the
|
||||
event filter function in the \a result parameter.
|
||||
Removes an event filter object \a obj from this object. The
|
||||
request is ignored if such an event filter has not been installed.
|
||||
|
||||
\sa setEventFilter()
|
||||
All event filters for this object are automatically removed when
|
||||
this object is destroyed.
|
||||
|
||||
It is always safe to remove an event filter, even during event
|
||||
filter activation (i.e. from the nativeEventFilter() function).
|
||||
|
||||
\sa installNativeEventFilter(), QAbstractNativeEventFilter
|
||||
\since 5.0
|
||||
*/
|
||||
bool QCoreApplication::filterEvent(void *message, long *result)
|
||||
void QCoreApplication::removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)
|
||||
{
|
||||
Q_D(QCoreApplication);
|
||||
if (result)
|
||||
*result = 0;
|
||||
if (d->eventFilter)
|
||||
return d->eventFilter(message, result);
|
||||
#ifdef Q_OS_WIN
|
||||
return winEventFilter(reinterpret_cast<MSG *>(message), result);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
|
||||
if (!filterObj || !eventDispatcher)
|
||||
return;
|
||||
eventDispatcher->removeNativeEventFilter(filterObj);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -61,6 +61,7 @@ class QTranslator;
|
||||
class QPostEventList;
|
||||
class QStringList;
|
||||
class QAbstractEventDispatcher;
|
||||
class QAbstractNativeEventFilter;
|
||||
|
||||
#define qApp QCoreApplication::instance()
|
||||
|
||||
@ -159,9 +160,9 @@ public:
|
||||
static void watchUnixSignal(int signal, bool watch);
|
||||
#endif
|
||||
|
||||
typedef bool (*EventFilter)(void *message, long *result);
|
||||
EventFilter setEventFilter(EventFilter filter);
|
||||
bool filterEvent(void *message, long *result);
|
||||
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj);
|
||||
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj);
|
||||
bool filterNativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||
|
||||
static bool isQuitLockEnabled();
|
||||
static void setQuitLockEnabled(bool enabled);
|
||||
|
@ -121,8 +121,6 @@ public:
|
||||
#endif
|
||||
uint application_type;
|
||||
|
||||
QCoreApplication::EventFilter eventFilter;
|
||||
|
||||
bool in_exec;
|
||||
bool aboutToQuitEmitted;
|
||||
bool threadData_clean;
|
||||
|
@ -207,12 +207,6 @@ void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
|
||||
the event to be processed by Qt, then return true and set \a result
|
||||
to the value that the window procedure should return. Otherwise
|
||||
return false.
|
||||
|
||||
It is only directly addressed messages that are filtered. To
|
||||
handle system wide messages, such as messages from a registered
|
||||
hot key, you need to install an event filter on the event
|
||||
dispatcher, which is returned from
|
||||
QAbstractEventDispatcher::instance().
|
||||
*/
|
||||
bool QCoreApplication::winEventFilter(MSG *msg, long *result) // Windows event filter
|
||||
{
|
||||
|
@ -359,7 +359,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
|
||||
if (message == WM_TIMER)
|
||||
KillTimer(hwnd, wp);
|
||||
return 0;
|
||||
} else if (app->filterEvent(&msg, &result)) {
|
||||
} else if (app->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -146,51 +146,4 @@ void QPlatformNativeInterface::setWindowProperty(QPlatformWindow *window, const
|
||||
Q_UNUSED(value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\typedef QPlatformNativeInterface::EventFilter
|
||||
\since 5.0
|
||||
|
||||
A function with the following signature that can be used as an
|
||||
event filter:
|
||||
|
||||
\code
|
||||
bool myEventFilter(void *message, long *result);
|
||||
\endcode
|
||||
|
||||
\sa setEventFilter()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn EventFilter QPlatformNativeInterface::setEventFilter(const QByteArray &eventType, EventFilter filter)
|
||||
\since 5.0
|
||||
|
||||
Replaces the event filter function for the native interface with
|
||||
\a filter and returns the pointer to the replaced event filter
|
||||
function. Only the current event filter function is called. If you
|
||||
want to use both filter functions, save the replaced EventFilter
|
||||
in a place where you can call it from.
|
||||
|
||||
The event filter function set here is called for all messages
|
||||
received from the platform if they are given type \eventType.
|
||||
It is \e not called for messages that are not meant for Qt objects.
|
||||
|
||||
The type of event is specific to the platform plugin chosen at run-time.
|
||||
|
||||
The event filter function should return \c true if the message should
|
||||
be filtered, (i.e. stopped). It should return \c false to allow
|
||||
processing the message to continue.
|
||||
|
||||
By default, no event filter function is set. For example, this function
|
||||
returns a null EventFilter the first time it is called.
|
||||
|
||||
\note The filter function here receives native messages,
|
||||
for example, MSG or XEvent structs. It is called by the platform plugin.
|
||||
*/
|
||||
QPlatformNativeInterface::EventFilter QPlatformNativeInterface::setEventFilter(const QByteArray &eventType, QPlatformNativeInterface::EventFilter filter)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(filter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -88,9 +88,6 @@ public:
|
||||
virtual QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
|
||||
virtual void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
|
||||
|
||||
typedef bool (*EventFilter)(void *message, long *result);
|
||||
virtual EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter);
|
||||
|
||||
Q_SIGNALS:
|
||||
void windowPropertyChanged(QPlatformWindow *window, const QString &propertyName);
|
||||
};
|
||||
|
@ -518,11 +518,6 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QAbstractEventDispatcher *ev
|
||||
break;
|
||||
}
|
||||
|
||||
if (eventDispatcher->filterEvent(event)) {
|
||||
delete event;
|
||||
continue;
|
||||
}
|
||||
|
||||
nevents++;
|
||||
|
||||
QGuiApplicationPrivate::processWindowSystemEvent(event);
|
||||
@ -554,7 +549,6 @@ QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *w, const QMi
|
||||
\brief Passes a native event identified by \a eventType to the \a window.
|
||||
|
||||
\note This function can only be called from the GUI thread.
|
||||
\sa QPlatformNativeInterface::setEventFilter()
|
||||
*/
|
||||
|
||||
bool QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result)
|
||||
|
@ -122,7 +122,6 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
QBBEngine::QBBEngine(QObject *parent) :
|
||||
QBearerEngineImpl(parent),
|
||||
previousEventFilter(0),
|
||||
pollingRequired(false),
|
||||
initialized(false)
|
||||
{
|
||||
@ -130,7 +129,6 @@ QBBEngine::QBBEngine(QObject *parent) :
|
||||
|
||||
QBBEngine::~QBBEngine()
|
||||
{
|
||||
QAbstractEventDispatcher::instance()->setEventFilter(previousEventFilter);
|
||||
}
|
||||
|
||||
|
||||
@ -173,8 +171,7 @@ void QBBEngine::initialize()
|
||||
const QMutexLocker locker(&pollingMutex);
|
||||
pollingRequired = true;
|
||||
} else {
|
||||
previousEventFilter =
|
||||
QAbstractEventDispatcher::instance()->setEventFilter(filterEvent);
|
||||
QAbstractEventDispatcher::instance()->installEventFilter(this);
|
||||
}
|
||||
|
||||
doRequestUpdate();
|
||||
@ -288,34 +285,23 @@ bool QBBEngine::requiresPolling() const
|
||||
return pollingRequired;
|
||||
}
|
||||
|
||||
bool QBBEngine::filterEvent(void *message)
|
||||
bool QBBEngine::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
|
||||
bps_event_t * const event = static_cast<bps_event_t *>(message);
|
||||
|
||||
Q_ASSERT(event);
|
||||
|
||||
QBBEngine *self = instanceStorage()->localData()->instance;
|
||||
|
||||
Q_ASSERT(self);
|
||||
|
||||
if (bps_event_get_domain(event) == netstatus_get_domain())
|
||||
self->filterEvent(event);
|
||||
|
||||
if (self->previousEventFilter)
|
||||
return self->previousEventFilter(message);
|
||||
if (bps_event_get_domain(event) == netstatus_get_domain()) {
|
||||
qBearerDebug() << Q_FUNC_INFO << "got update request.";
|
||||
doRequestUpdate();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void QBBEngine::filterEvent(bps_event_t *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
qBearerDebug() << Q_FUNC_INFO << "got update request.";
|
||||
|
||||
doRequestUpdate();
|
||||
}
|
||||
|
||||
void QBBEngine::updateConfiguration(const char *interface)
|
||||
{
|
||||
netstatus_interface_details_t *details = 0;
|
||||
@ -421,4 +407,3 @@ void QBBEngine::removeConfiguration(const QString &id)
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_BEARERMANAGEMENT
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "../qbearerengine_impl.h"
|
||||
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
|
||||
@ -55,7 +56,7 @@ QT_BEGIN_NAMESPACE
|
||||
class QNetworkConfigurationPrivate;
|
||||
class QNetworkSessionPrivate;
|
||||
|
||||
class QBBEngine : public QBearerEngineImpl
|
||||
class QBBEngine : public QBearerEngineImpl, public QAbstractNativeEventFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -82,6 +83,8 @@ public:
|
||||
|
||||
bool requiresPolling() const Q_DECL_OVERRIDE;
|
||||
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
||||
|
||||
protected:
|
||||
void updateConfiguration(const char *interface);
|
||||
void removeConfiguration(const QString &id);
|
||||
@ -90,14 +93,8 @@ private Q_SLOTS:
|
||||
void doRequestUpdate();
|
||||
|
||||
private:
|
||||
static bool filterEvent(void *message);
|
||||
|
||||
void filterEvent(bps_event_t *event);
|
||||
|
||||
QHash<QString, QString> configurationInterface;
|
||||
|
||||
QAbstractEventDispatcher::EventFilter previousEventFilter;
|
||||
|
||||
mutable QMutex pollingMutex;
|
||||
|
||||
bool pollingRequired;
|
||||
|
@ -90,13 +90,7 @@ void QQnxBpsEventFilter::installOnEventDispatcher(QAbstractEventDispatcher *disp
|
||||
if (navigator_request_events(0) != BPS_SUCCESS)
|
||||
qWarning("QQNX: failed to register for navigator events");
|
||||
|
||||
QAbstractEventDispatcher::EventFilter previousEventFilter = dispatcher->setEventFilter(dispatcherEventFilter);
|
||||
|
||||
// the QPA plugin creates the event dispatcher so we are the first event
|
||||
// filter assert on that just in case somebody adds another event filter
|
||||
// in the QQnxIntegration constructor instead of adding a new section in here
|
||||
Q_ASSERT(previousEventFilter == 0);
|
||||
Q_UNUSED(previousEventFilter);
|
||||
dispatcher->installNativeEventFilter(this);
|
||||
}
|
||||
|
||||
void QQnxBpsEventFilter::registerForScreenEvents(QQnxScreen *screen)
|
||||
@ -137,19 +131,11 @@ void QQnxBpsEventFilter::unregisterForDialogEvents(QQnxFileDialogHelper *dialog)
|
||||
qWarning("QQNX: attempting to unregister dialog that was not registered");
|
||||
}
|
||||
|
||||
bool QQnxBpsEventFilter::dispatcherEventFilter(void *message)
|
||||
bool QQnxBpsEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
qBpsEventFilterDebug() << Q_FUNC_INFO;
|
||||
|
||||
if (s_instance == 0)
|
||||
return false;
|
||||
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
bps_event_t *event = static_cast<bps_event_t *>(message);
|
||||
return s_instance->bpsEventFilter(event);
|
||||
}
|
||||
|
||||
bool QQnxBpsEventFilter::bpsEventFilter(bps_event_t *event)
|
||||
{
|
||||
const int eventDomain = bps_event_get_domain(event);
|
||||
qBpsEventFilterDebug() << Q_FUNC_INFO << "event=" << event << "domain=" << eventDomain;
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
#include <bps/dialog.h>
|
||||
|
||||
@ -58,7 +59,7 @@ class QQnxScreen;
|
||||
class QQnxScreenEventHandler;
|
||||
class QQnxVirtualKeyboardBps;
|
||||
|
||||
class QQnxBpsEventFilter : public QObject
|
||||
class QQnxBpsEventFilter : public QObject, public QAbstractNativeEventFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -76,8 +77,7 @@ public:
|
||||
void unregisterForDialogEvents(QQnxFileDialogHelper *dialog);
|
||||
|
||||
private:
|
||||
static bool dispatcherEventFilter(void *message);
|
||||
bool bpsEventFilter(bps_event_t *event);
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
||||
|
||||
bool handleNavigatorEvent(bps_event_t *event);
|
||||
|
||||
|
@ -240,13 +240,6 @@ QWindowsContext *QWindowsContext::m_instance = 0;
|
||||
typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash;
|
||||
|
||||
struct QWindowsContextPrivate {
|
||||
typedef QPlatformNativeInterface::EventFilter EventFilter;
|
||||
|
||||
enum EventFilterType
|
||||
{
|
||||
GenericWindowsEventFilter,
|
||||
EventFilterTypeCount
|
||||
};
|
||||
|
||||
QWindowsContextPrivate();
|
||||
|
||||
@ -262,7 +255,6 @@ struct QWindowsContextPrivate {
|
||||
QSharedPointer<QWindowCreationContext> m_creationContext;
|
||||
const HRESULT m_oleInitializeResult;
|
||||
const QByteArray m_eventType;
|
||||
EventFilter m_eventFilters[EventFilterTypeCount];
|
||||
QWindow *m_lastActiveWindow;
|
||||
};
|
||||
|
||||
@ -289,7 +281,6 @@ QWindowsContextPrivate::QWindowsContextPrivate() :
|
||||
m_systemInfo |= QWindowsContext::SI_RTL_Extensions;
|
||||
m_keyMapper.setUseRTLExtensions(true);
|
||||
}
|
||||
qFill(m_eventFilters, m_eventFilters + EventFilterTypeCount, EventFilter(0));
|
||||
}
|
||||
|
||||
QWindowsContext::QWindowsContext() :
|
||||
@ -694,27 +685,6 @@ QByteArray QWindowsContext::comErrorString(HRESULT hr)
|
||||
return "Unknown error 0x" + QByteArray::number(quint64(hr), 16);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set event filter.
|
||||
|
||||
\sa QWindowsNativeInterface
|
||||
*/
|
||||
|
||||
QWindowsContext::EventFilter QWindowsContext::setEventFilter(const QByteArray &eventType, EventFilter filter)
|
||||
{
|
||||
int eventFilterType = -1;
|
||||
if (eventType == d->m_eventType)
|
||||
eventFilterType = QWindowsContextPrivate::GenericWindowsEventFilter;
|
||||
if (eventFilterType < 0) {
|
||||
qWarning("%s: Attempt to set unsupported event filter '%s'.",
|
||||
__FUNCTION__, eventType.constData());
|
||||
return 0;
|
||||
}
|
||||
const EventFilter previous = d->m_eventFilters[eventFilterType];
|
||||
d->m_eventFilters[eventFilterType] = filter;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Main windows procedure registered for windows.
|
||||
|
||||
@ -736,11 +706,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
||||
msg.pt.y = GET_Y_LPARAM(lParam);
|
||||
|
||||
long filterResult = 0;
|
||||
if (d->m_eventFilters[QWindowsContextPrivate::GenericWindowsEventFilter]) {
|
||||
if (d->m_eventFilters[QWindowsContextPrivate::GenericWindowsEventFilter](&msg, &filterResult)) {
|
||||
*result = LRESULT(filterResult);
|
||||
return true;
|
||||
}
|
||||
QCoreApplication* coreApp = QCoreApplication::instance();
|
||||
if (coreApp && coreApp->filterNativeEvent(d->m_eventType, &msg, &filterResult)) {
|
||||
*result = LRESULT(filterResult);
|
||||
return true;
|
||||
}
|
||||
// Events without an associated QWindow or events we are not interested in.
|
||||
switch (et) {
|
||||
|
@ -107,7 +107,6 @@ class QWindowsContext
|
||||
{
|
||||
Q_DISABLE_COPY(QWindowsContext)
|
||||
public:
|
||||
typedef bool (*EventFilter)(void *message, long *result);
|
||||
|
||||
enum SystemInfoFlags
|
||||
{
|
||||
@ -143,8 +142,6 @@ public:
|
||||
HDC displayContext() const;
|
||||
int screenDepth() const;
|
||||
|
||||
EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter);
|
||||
|
||||
static QWindowsContext *instance();
|
||||
|
||||
static QString windowsErrorMessage(unsigned long errorCode);
|
||||
|
@ -102,8 +102,6 @@ public:
|
||||
#endif
|
||||
virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
|
||||
virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs);
|
||||
virtual EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter)
|
||||
{ return QWindowsContext::instance()->setEventFilter(eventType, filter); }
|
||||
|
||||
Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
|
||||
const QString &windowName,
|
||||
|
@ -270,7 +270,6 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
|
||||
{ \
|
||||
event_t *e = (event_t *)event; \
|
||||
if (QXcbWindow *platformWindow = platformWindowFromId(e->windowMember)) { \
|
||||
long result = 0; \
|
||||
handled = QWindowSystemInterface::handleNativeEvent(platformWindow->window(), m_nativeInterface->genericEventFilterType(), event, &result); \
|
||||
if (!handled) \
|
||||
platformWindow->handler(e); \
|
||||
@ -282,7 +281,6 @@ break;
|
||||
{ \
|
||||
event_t *e = (event_t *)event; \
|
||||
if (QXcbWindow *platformWindow = platformWindowFromId(e->event)) { \
|
||||
long result = 0; \
|
||||
handled = QWindowSystemInterface::handleNativeEvent(platformWindow->window(), m_nativeInterface->genericEventFilterType(), event, &result); \
|
||||
if (!handled) \
|
||||
m_keyboard->handler(platformWindow, e); \
|
||||
@ -543,10 +541,9 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
||||
m_callLog.remove(0, i);
|
||||
}
|
||||
#endif
|
||||
bool handled = false;
|
||||
|
||||
if (QPlatformNativeInterface::EventFilter filter = m_nativeInterface->eventFilter(QXcbNativeInterface::GenericEventFilter))
|
||||
handled = filter(event, 0);
|
||||
long result = 0;
|
||||
bool handled = QCoreApplication::instance()->filterNativeEvent(m_nativeInterface->genericEventFilterType(), event, &result);
|
||||
|
||||
uint response_type = event->response_type & ~0x80;
|
||||
|
||||
|
@ -80,7 +80,6 @@ QXcbNativeInterface::QXcbNativeInterface() :
|
||||
m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t"))
|
||||
|
||||
{
|
||||
qFill(m_eventFilters, m_eventFilters + EventFilterCount, EventFilter(0));
|
||||
}
|
||||
|
||||
void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context)
|
||||
@ -142,21 +141,6 @@ QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::
|
||||
return 0;
|
||||
}
|
||||
|
||||
QPlatformNativeInterface::EventFilter QXcbNativeInterface::setEventFilter(const QByteArray &eventType, QPlatformNativeInterface::EventFilter filter)
|
||||
{
|
||||
int type = -1;
|
||||
if (eventType == m_genericEventFilterType)
|
||||
type = GenericEventFilter;
|
||||
if (type == -1) {
|
||||
qWarning("QXcbNativeInterface: %s: Attempt to set invalid event filter type '%s'.",
|
||||
Q_FUNC_INFO, eventType.constData());
|
||||
return 0;
|
||||
}
|
||||
const EventFilter oldFilter = m_eventFilters[type];
|
||||
m_eventFilters[type] = filter;
|
||||
return oldFilter;
|
||||
}
|
||||
|
||||
QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window)
|
||||
{
|
||||
QXcbScreen *screen;
|
||||
|
@ -61,11 +61,6 @@ public:
|
||||
EglContext
|
||||
};
|
||||
|
||||
enum EventFilterType {
|
||||
GenericEventFilter,
|
||||
EventFilterCount
|
||||
};
|
||||
|
||||
QXcbNativeInterface();
|
||||
|
||||
void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
|
||||
@ -74,8 +69,6 @@ public:
|
||||
NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource);
|
||||
|
||||
inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; }
|
||||
EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter);
|
||||
EventFilter eventFilter(EventFilterType type) const { return m_eventFilters[type]; }
|
||||
|
||||
void *displayForWindow(QWindow *window);
|
||||
void *eglDisplayForWindow(QWindow *window);
|
||||
@ -86,7 +79,6 @@ public:
|
||||
|
||||
private:
|
||||
const QByteArray m_genericEventFilterType;
|
||||
EventFilter m_eventFilters[EventFilterCount];
|
||||
|
||||
static QXcbScreen *qPlatformScreenForWindow(QWindow *window);
|
||||
};
|
||||
|
@ -46,8 +46,10 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QAbstractEventDispatcher::EventFilter oldEventFilter = 0;
|
||||
qint64 QBenchmarkEvent::eventCounter = 0;
|
||||
QBenchmarkEvent::QBenchmarkEvent()
|
||||
: eventCounter(0)
|
||||
{
|
||||
}
|
||||
|
||||
QBenchmarkEvent::~QBenchmarkEvent()
|
||||
{
|
||||
@ -55,21 +57,19 @@ QBenchmarkEvent::~QBenchmarkEvent()
|
||||
|
||||
void QBenchmarkEvent::start()
|
||||
{
|
||||
QBenchmarkEvent::eventCounter = 0;
|
||||
QAbstractEventDispatcher *parent = QAbstractEventDispatcher::instance();
|
||||
oldEventFilter = parent->setEventFilter(QBenchmarkEvent::eventCountingMechanism);
|
||||
eventCounter = 0;
|
||||
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
|
||||
}
|
||||
|
||||
qint64 QBenchmarkEvent::checkpoint()
|
||||
{
|
||||
return QBenchmarkEvent::eventCounter;
|
||||
return eventCounter;
|
||||
}
|
||||
|
||||
qint64 QBenchmarkEvent::stop()
|
||||
{
|
||||
QAbstractEventDispatcher *parent = QAbstractEventDispatcher::instance();
|
||||
parent->setEventFilter(oldEventFilter);
|
||||
return QBenchmarkEvent::eventCounter;
|
||||
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
|
||||
return eventCounter;
|
||||
}
|
||||
|
||||
// It's very tempting to simply reject a measurement if 0 events
|
||||
@ -98,10 +98,13 @@ QTest::QBenchmarkMetric QBenchmarkEvent::metricType()
|
||||
}
|
||||
|
||||
// This could be done in a much better way, this is just the beginning.
|
||||
bool QBenchmarkEvent::eventCountingMechanism(void *message)
|
||||
bool QBenchmarkEvent::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(message);
|
||||
QBenchmarkEvent::eventCounter++;
|
||||
Q_UNUSED(result);
|
||||
|
||||
eventCounter++;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -56,12 +56,14 @@
|
||||
#include <QtTest/private/qbenchmarkmeasurement_p.h>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QObject>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QBenchmarkEvent : public QBenchmarkMeasurerBase
|
||||
class QBenchmarkEvent : public QBenchmarkMeasurerBase, public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
QBenchmarkEvent();
|
||||
~QBenchmarkEvent();
|
||||
void start();
|
||||
qint64 checkpoint();
|
||||
@ -71,8 +73,8 @@ public:
|
||||
int adjustMedianCount(int suggestion);
|
||||
bool repeatCount() { return 1; }
|
||||
QTest::QBenchmarkMetric metricType();
|
||||
static bool eventCountingMechanism(void *message);
|
||||
static qint64 eventCounter;
|
||||
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
|
||||
qint64 eventCounter;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -87,7 +87,7 @@ void tst_BenchlibEventCounter::events()
|
||||
QAbstractEventDispatcher* ed = QAbstractEventDispatcher::instance();
|
||||
QBENCHMARK {
|
||||
for (int i = 0; i < eventCount; ++i) {
|
||||
ed->filterEvent(0);
|
||||
ed->filterNativeEvent("", 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,9 +88,9 @@ void tst_BenchlibOptions::threeEvents()
|
||||
{
|
||||
QAbstractEventDispatcher* ed = QAbstractEventDispatcher::instance();
|
||||
QBENCHMARK {
|
||||
ed->filterEvent(0);
|
||||
ed->filterEvent(0);
|
||||
ed->filterEvent(0);
|
||||
ed->filterNativeEvent("", 0, 0);
|
||||
ed->filterNativeEvent("", 0, 0);
|
||||
ed->filterNativeEvent("", 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@
|
||||
#include <qcompleter.h>
|
||||
#include <qtableview.h>
|
||||
#include <qtreewidget.h>
|
||||
#include <qabstractnativeeventfilter.h>
|
||||
|
||||
#include <QtWidgets/QGraphicsView>
|
||||
#include <QtWidgets/QGraphicsProxyWidget>
|
||||
@ -5505,16 +5506,17 @@ void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
|
||||
}
|
||||
}
|
||||
|
||||
class ShowHideShowWidget : public QWidget
|
||||
class ShowHideShowWidget : public QWidget, public QAbstractNativeEventFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
int state;
|
||||
public:
|
||||
bool gotExpectedMapNotify;
|
||||
bool gotExpectedGlobalEvent;
|
||||
|
||||
ShowHideShowWidget()
|
||||
: state(0), gotExpectedMapNotify(false)
|
||||
: state(0), gotExpectedMapNotify(false), gotExpectedGlobalEvent(false)
|
||||
{
|
||||
startTimer(1000);
|
||||
}
|
||||
@ -5531,19 +5533,32 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool nativeEvent(const QByteArray &eventType, void *message, long *)
|
||||
bool isMapNotify(const QByteArray &eventType, void *message)
|
||||
{
|
||||
enum { XCB_MAP_NOTIFY = 19 };
|
||||
|
||||
if (state == 1 && eventType == QByteArrayLiteral("xcb_generic_event_t")) {
|
||||
// XCB events have a uint8 response_type member at the beginning.
|
||||
const unsigned char responseType = *(const unsigned char *)(message);
|
||||
if ((responseType & ~0x80) == XCB_MAP_NOTIFY)
|
||||
gotExpectedMapNotify = true;
|
||||
return ((responseType & ~0x80) == XCB_MAP_NOTIFY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool nativeEvent(const QByteArray &eventType, void *message, long *)
|
||||
{
|
||||
if (isMapNotify(eventType, message))
|
||||
gotExpectedMapNotify = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// QAbstractNativeEventFilter interface
|
||||
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
|
||||
{
|
||||
if (isMapNotify(eventType, message))
|
||||
gotExpectedGlobalEvent = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
signals:
|
||||
void done();
|
||||
};
|
||||
@ -5554,6 +5569,8 @@ void tst_QWidget::showHideShowX11()
|
||||
QSKIP("This test is for X11 only.");
|
||||
|
||||
ShowHideShowWidget w;
|
||||
qApp->installNativeEventFilter(&w);
|
||||
|
||||
w.show();
|
||||
w.hide();
|
||||
|
||||
@ -5561,6 +5578,7 @@ void tst_QWidget::showHideShowX11()
|
||||
connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
|
||||
eventLoop.exec();
|
||||
|
||||
QVERIFY(w.gotExpectedGlobalEvent);
|
||||
QVERIFY(w.gotExpectedMapNotify);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user