Add support for platform plugin specific event filters.

The setEventFilter on the platform native interface allows subscribing to
events on the backend by event name.

Change-Id: Ib10077fbc69f0207edbae1177e7bbd18c8d0f9ae
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
Reviewed-by: Michalina Ziemba <michalina.ziemba@nokia.com>
This commit is contained in:
Simon Hausmann 2012-01-18 15:16:09 +01:00 committed by Qt by Nokia
parent 8060dd3c42
commit 1ca05bb0c1
8 changed files with 147 additions and 69 deletions

View File

@ -106,4 +106,51 @@ void QPlatformNativeInterface::setWindowProperty(QPlatformWindow *window, const
Q_UNUSED(value); 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 \i 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 QT_END_NAMESPACE

View File

@ -70,6 +70,9 @@ public:
virtual QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const; virtual QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
virtual void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value); 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: Q_SIGNALS:
void windowPropertyChanged(QPlatformWindow *window, const QString &propertyName); void windowPropertyChanged(QPlatformWindow *window, const QString &propertyName);
}; };

View File

@ -49,11 +49,13 @@
#include "qxcbclipboard.h" #include "qxcbclipboard.h"
#include "qxcbdrag.h" #include "qxcbdrag.h"
#include "qxcbwmsupport.h" #include "qxcbwmsupport.h"
#include "qxcbnativeinterface.h"
#include <QtAlgorithms> #include <QtAlgorithms>
#include <QSocketNotifier> #include <QSocketNotifier>
#include <QAbstractEventDispatcher> #include <QAbstractEventDispatcher>
#include <QTimer> #include <QTimer>
#include <QByteArray>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
@ -93,9 +95,10 @@ static int nullErrorHandler(Display *, XErrorEvent *)
} }
#endif #endif
QXcbConnection::QXcbConnection(const char *displayName) QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char *displayName)
: m_connection(0) : m_connection(0)
, m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
, m_nativeInterface(nativeInterface)
#ifdef XCB_USE_XINPUT2_MAEMO #ifdef XCB_USE_XINPUT2_MAEMO
, m_xinputData(0) , m_xinputData(0)
#endif #endif
@ -493,72 +496,77 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
m_callLog.remove(0, i); m_callLog.remove(0, i);
} }
#endif #endif
bool handled = true; bool handled = false;
if (QPlatformNativeInterface::EventFilter filter = m_nativeInterface->eventFilterForEventType(QByteArrayLiteral("xcb_generic_event_t")))
handled = filter(event, 0);
uint response_type = event->response_type & ~0x80; uint response_type = event->response_type & ~0x80;
switch (response_type) { if (!handled) {
case XCB_EXPOSE: switch (response_type) {
HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); case XCB_EXPOSE:
case XCB_BUTTON_PRESS: HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE: HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); case XCB_BUTTON_RELEASE:
case XCB_MOTION_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); case XCB_MOTION_NOTIFY:
case XCB_CONFIGURE_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); case XCB_CONFIGURE_NOTIFY:
case XCB_MAP_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent); case XCB_MAP_NOTIFY:
case XCB_UNMAP_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent); case XCB_UNMAP_NOTIFY:
case XCB_CLIENT_MESSAGE: HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
handleClientMessageEvent((xcb_client_message_event_t *)event); case XCB_CLIENT_MESSAGE:
case XCB_ENTER_NOTIFY: handleClientMessageEvent((xcb_client_message_event_t *)event);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); case XCB_ENTER_NOTIFY:
case XCB_LEAVE_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); case XCB_LEAVE_NOTIFY:
case XCB_FOCUS_IN: HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); case XCB_FOCUS_IN:
case XCB_FOCUS_OUT: HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); case XCB_FOCUS_OUT:
case XCB_KEY_PRESS: HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); case XCB_KEY_PRESS:
case XCB_KEY_RELEASE: HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); case XCB_KEY_RELEASE:
case XCB_MAPPING_NOTIFY: HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); case XCB_MAPPING_NOTIFY:
break; m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
case XCB_SELECTION_REQUEST: break;
{ case XCB_SELECTION_REQUEST:
xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event; {
if (sr->selection == atom(QXcbAtom::XdndSelection)) xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
m_drag->handleSelectionRequest(sr); if (sr->selection == atom(QXcbAtom::XdndSelection))
else m_drag->handleSelectionRequest(sr);
m_clipboard->handleSelectionRequest(sr); else
break; m_clipboard->handleSelectionRequest(sr);
} break;
case XCB_SELECTION_CLEAR: }
setTime(((xcb_selection_clear_event_t *)event)->time); case XCB_SELECTION_CLEAR:
m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event); setTime(((xcb_selection_clear_event_t *)event)->time);
handled = true; m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event);
break; handled = true;
case XCB_SELECTION_NOTIFY: break;
setTime(((xcb_selection_notify_event_t *)event)->time); case XCB_SELECTION_NOTIFY:
qDebug() << "XCB_SELECTION_NOTIFY"; setTime(((xcb_selection_notify_event_t *)event)->time);
handled = false; qDebug() << "XCB_SELECTION_NOTIFY";
break; handled = false;
case XCB_PROPERTY_NOTIFY: break;
HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); case XCB_PROPERTY_NOTIFY:
break; HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
#ifdef XCB_USE_XINPUT2_MAEMO break;
case GenericEvent: #ifdef XCB_USE_XINPUT2_MAEMO
handleGenericEvent((xcb_ge_event_t*)event); case GenericEvent:
break; handleGenericEvent((xcb_ge_event_t*)event);
#endif break;
default: #endif
handled = false; default:
break; handled = false;
break;
}
} }
if (!handled) { if (!handled) {

View File

@ -66,6 +66,7 @@ class QXcbDrag;
class QXcbKeyboard; class QXcbKeyboard;
class QXcbClipboard; class QXcbClipboard;
class QXcbWMSupport; class QXcbWMSupport;
class QXcbNativeInterface;
typedef QHash<xcb_window_t, QXcbWindow *> WindowMapper; typedef QHash<xcb_window_t, QXcbWindow *> WindowMapper;
@ -289,7 +290,7 @@ class QXcbConnection : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
QXcbConnection(const char *displayName = 0); QXcbConnection(QXcbNativeInterface *nativeInterface, const char *displayName = 0);
~QXcbConnection(); ~QXcbConnection();
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); } QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
@ -390,6 +391,7 @@ private:
QXcbClipboard *m_clipboard; QXcbClipboard *m_clipboard;
QXcbDrag *m_drag; QXcbDrag *m_drag;
QScopedPointer<QXcbWMSupport> m_wmSupport; QScopedPointer<QXcbWMSupport> m_wmSupport;
QXcbNativeInterface *m_nativeInterface;
#if defined(XCB_USE_XLIB) #if defined(XCB_USE_XLIB)
void *m_xlib_display; void *m_xlib_display;

View File

@ -90,13 +90,14 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
#ifdef XCB_USE_XLIB #ifdef XCB_USE_XLIB
XInitThreads(); XInitThreads();
#endif #endif
m_nativeInterface.reset(new QXcbNativeInterface);
m_connections << new QXcbConnection; m_connections << new QXcbConnection(m_nativeInterface.data());
for (int i = 0; i < parameters.size() - 1; i += 2) { for (int i = 0; i < parameters.size() - 1; i += 2) {
qDebug() << parameters.at(i) << parameters.at(i+1); qDebug() << parameters.at(i) << parameters.at(i+1);
QString display = parameters.at(i) + ':' + parameters.at(i+1); QString display = parameters.at(i) + ':' + parameters.at(i+1);
m_connections << new QXcbConnection(display.toAscii().constData()); m_connections << new QXcbConnection(m_nativeInterface.data(), display.toAscii().constData());
} }
foreach (QXcbConnection *connection, m_connections) foreach (QXcbConnection *connection, m_connections)
@ -104,7 +105,6 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
screenAdded(screen); screenAdded(screen);
m_fontDatabase.reset(new QGenericUnixFontDatabase()); m_fontDatabase.reset(new QGenericUnixFontDatabase());
m_nativeInterface.reset(new QXcbNativeInterface);
m_inputContext.reset(QPlatformInputContextFactory::create()); m_inputContext.reset(QPlatformInputContextFactory::create());
m_accessibility.reset(new QPlatformAccessibility()); m_accessibility.reset(new QPlatformAccessibility());
} }

View File

@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE
class QXcbConnection; class QXcbConnection;
class QAbstractEventDispatcher; class QAbstractEventDispatcher;
class QXcbNativeInterface;
class QXcbIntegration : public QPlatformIntegration class QXcbIntegration : public QPlatformIntegration
{ {
@ -80,7 +81,7 @@ private:
QList<QXcbConnection *> m_connections; QList<QXcbConnection *> m_connections;
QScopedPointer<QPlatformFontDatabase> m_fontDatabase; QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
QScopedPointer<QPlatformNativeInterface> m_nativeInterface; QScopedPointer<QXcbNativeInterface> m_nativeInterface;
QScopedPointer<QPlatformInputContext> m_inputContext; QScopedPointer<QPlatformInputContext> m_inputContext;
QAbstractEventDispatcher *m_eventDispatcher; QAbstractEventDispatcher *m_eventDispatcher;

View File

@ -118,6 +118,18 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr
return result; return result;
} }
QPlatformNativeInterface::EventFilter QXcbNativeInterface::setEventFilter(const QByteArray &eventType, QPlatformNativeInterface::EventFilter filter)
{
EventFilter oldFilter = m_eventFilters.value(eventType);
m_eventFilters.insert(eventType, filter);
return oldFilter;
}
QPlatformNativeInterface::EventFilter QXcbNativeInterface::eventFilterForEventType(const QByteArray& eventType) const
{
return m_eventFilters.value(eventType);
}
QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window) QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window)
{ {
QXcbScreen *screen; QXcbScreen *screen;

View File

@ -64,6 +64,9 @@ public:
void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context); void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window);
EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter);
EventFilter eventFilterForEventType(const QByteArray& eventType) const;
void *displayForWindow(QWindow *window); void *displayForWindow(QWindow *window);
void *eglDisplayForWindow(QWindow *window); void *eglDisplayForWindow(QWindow *window);
void *connectionForWindow(QWindow *window); void *connectionForWindow(QWindow *window);
@ -73,6 +76,8 @@ public:
void *eglContextForContext(QOpenGLContext *context); void *eglContextForContext(QOpenGLContext *context);
private: private:
QHash<QByteArray, EventFilter> m_eventFilters;
static QXcbScreen *qPlatformScreenForWindow(QWindow *window); static QXcbScreen *qPlatformScreenForWindow(QWindow *window);
}; };