From 1ca05bb0c174d505469ac647818afaf537b41f43 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 18 Jan 2012 15:16:09 +0100 Subject: Add support for platform plugin specific event filters. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Michalina Ziemba --- src/gui/kernel/qplatformnativeinterface_qpa.cpp | 47 ++++++++ src/gui/kernel/qplatformnativeinterface_qpa.h | 3 + src/plugins/platforms/xcb/qxcbconnection.cpp | 136 ++++++++++++---------- src/plugins/platforms/xcb/qxcbconnection.h | 4 +- src/plugins/platforms/xcb/qxcbintegration.cpp | 6 +- src/plugins/platforms/xcb/qxcbintegration.h | 3 +- src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 12 ++ src/plugins/platforms/xcb/qxcbnativeinterface.h | 5 + 8 files changed, 147 insertions(+), 69 deletions(-) diff --git a/src/gui/kernel/qplatformnativeinterface_qpa.cpp b/src/gui/kernel/qplatformnativeinterface_qpa.cpp index f9ddd1f72a..626f6a1e51 100644 --- a/src/gui/kernel/qplatformnativeinterface_qpa.cpp +++ b/src/gui/kernel/qplatformnativeinterface_qpa.cpp @@ -106,4 +106,51 @@ 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 \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 diff --git a/src/gui/kernel/qplatformnativeinterface_qpa.h b/src/gui/kernel/qplatformnativeinterface_qpa.h index 47e2f82810..579a0bcd9b 100644 --- a/src/gui/kernel/qplatformnativeinterface_qpa.h +++ b/src/gui/kernel/qplatformnativeinterface_qpa.h @@ -70,6 +70,9 @@ 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); }; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index afc6c18c4f..230ce89769 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -49,11 +49,13 @@ #include "qxcbclipboard.h" #include "qxcbdrag.h" #include "qxcbwmsupport.h" +#include "qxcbnativeinterface.h" #include #include #include #include +#include #include #include @@ -93,9 +95,10 @@ static int nullErrorHandler(Display *, XErrorEvent *) } #endif -QXcbConnection::QXcbConnection(const char *displayName) +QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char *displayName) : m_connection(0) , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) + , m_nativeInterface(nativeInterface) #ifdef XCB_USE_XINPUT2_MAEMO , m_xinputData(0) #endif @@ -493,72 +496,77 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) m_callLog.remove(0, i); } #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; - switch (response_type) { - case XCB_EXPOSE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); - case XCB_BUTTON_PRESS: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); - case XCB_BUTTON_RELEASE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); - case XCB_MOTION_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); - case XCB_CONFIGURE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); - case XCB_MAP_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent); - case XCB_UNMAP_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent); - case XCB_CLIENT_MESSAGE: - handleClientMessageEvent((xcb_client_message_event_t *)event); - case XCB_ENTER_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); - case XCB_LEAVE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); - case XCB_FOCUS_IN: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); - case XCB_FOCUS_OUT: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); - case XCB_KEY_PRESS: - HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); - case XCB_KEY_RELEASE: - HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); - case XCB_MAPPING_NOTIFY: - m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); - break; - case XCB_SELECTION_REQUEST: - { - xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event; - if (sr->selection == atom(QXcbAtom::XdndSelection)) - m_drag->handleSelectionRequest(sr); - else - m_clipboard->handleSelectionRequest(sr); - break; - } - case XCB_SELECTION_CLEAR: - setTime(((xcb_selection_clear_event_t *)event)->time); - m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event); - handled = true; - break; - case XCB_SELECTION_NOTIFY: - setTime(((xcb_selection_notify_event_t *)event)->time); - qDebug() << "XCB_SELECTION_NOTIFY"; - handled = false; - break; - case XCB_PROPERTY_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); - break; -#ifdef XCB_USE_XINPUT2_MAEMO - case GenericEvent: - handleGenericEvent((xcb_ge_event_t*)event); - break; -#endif - default: - handled = false; - break; + if (!handled) { + switch (response_type) { + case XCB_EXPOSE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); + case XCB_BUTTON_PRESS: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); + case XCB_BUTTON_RELEASE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); + case XCB_MOTION_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); + case XCB_CONFIGURE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); + case XCB_MAP_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent); + case XCB_UNMAP_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent); + case XCB_CLIENT_MESSAGE: + handleClientMessageEvent((xcb_client_message_event_t *)event); + case XCB_ENTER_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); + case XCB_LEAVE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); + case XCB_FOCUS_IN: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); + case XCB_FOCUS_OUT: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); + case XCB_KEY_PRESS: + HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + case XCB_KEY_RELEASE: + HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); + case XCB_MAPPING_NOTIFY: + m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); + break; + case XCB_SELECTION_REQUEST: + { + xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event; + if (sr->selection == atom(QXcbAtom::XdndSelection)) + m_drag->handleSelectionRequest(sr); + else + m_clipboard->handleSelectionRequest(sr); + break; + } + case XCB_SELECTION_CLEAR: + setTime(((xcb_selection_clear_event_t *)event)->time); + m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event); + handled = true; + break; + case XCB_SELECTION_NOTIFY: + setTime(((xcb_selection_notify_event_t *)event)->time); + qDebug() << "XCB_SELECTION_NOTIFY"; + handled = false; + break; + case XCB_PROPERTY_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); + break; + #ifdef XCB_USE_XINPUT2_MAEMO + case GenericEvent: + handleGenericEvent((xcb_ge_event_t*)event); + break; + #endif + default: + handled = false; + break; + } } if (!handled) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 1feba558c9..a02acecd6c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -66,6 +66,7 @@ class QXcbDrag; class QXcbKeyboard; class QXcbClipboard; class QXcbWMSupport; +class QXcbNativeInterface; typedef QHash WindowMapper; @@ -289,7 +290,7 @@ class QXcbConnection : public QObject { Q_OBJECT public: - QXcbConnection(const char *displayName = 0); + QXcbConnection(QXcbNativeInterface *nativeInterface, const char *displayName = 0); ~QXcbConnection(); QXcbConnection *connection() const { return const_cast(this); } @@ -390,6 +391,7 @@ private: QXcbClipboard *m_clipboard; QXcbDrag *m_drag; QScopedPointer m_wmSupport; + QXcbNativeInterface *m_nativeInterface; #if defined(XCB_USE_XLIB) void *m_xlib_display; diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 3cf50cbbd9..418915bd15 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -90,13 +90,14 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters) #ifdef XCB_USE_XLIB XInitThreads(); #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) { qDebug() << 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) @@ -104,7 +105,6 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters) screenAdded(screen); m_fontDatabase.reset(new QGenericUnixFontDatabase()); - m_nativeInterface.reset(new QXcbNativeInterface); m_inputContext.reset(QPlatformInputContextFactory::create()); m_accessibility.reset(new QPlatformAccessibility()); } diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 8a3926dbfb..2bb5f1e65e 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE class QXcbConnection; class QAbstractEventDispatcher; +class QXcbNativeInterface; class QXcbIntegration : public QPlatformIntegration { @@ -80,7 +81,7 @@ private: QList m_connections; QScopedPointer m_fontDatabase; - QScopedPointer m_nativeInterface; + QScopedPointer m_nativeInterface; QScopedPointer m_inputContext; QAbstractEventDispatcher *m_eventDispatcher; diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 52ff30991e..535d66aa39 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -118,6 +118,18 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr 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 *screen; diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 517e92bc64..fae2a3c4fb 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -64,6 +64,9 @@ public: void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context); 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 *eglDisplayForWindow(QWindow *window); void *connectionForWindow(QWindow *window); @@ -73,6 +76,8 @@ public: void *eglContextForContext(QOpenGLContext *context); private: + QHash m_eventFilters; + static QXcbScreen *qPlatformScreenForWindow(QWindow *window); }; -- cgit v1.2.3