Add support for platform plugin specific event filters.
authorSimon Hausmann <simon.hausmann@nokia.com>
Wed, 18 Jan 2012 14:16:09 +0000 (15:16 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 20 Jan 2012 11:43:52 +0000 (12:43 +0100)
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>
src/gui/kernel/qplatformnativeinterface_qpa.cpp
src/gui/kernel/qplatformnativeinterface_qpa.h
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbconnection.h
src/plugins/platforms/xcb/qxcbintegration.cpp
src/plugins/platforms/xcb/qxcbintegration.h
src/plugins/platforms/xcb/qxcbnativeinterface.cpp
src/plugins/platforms/xcb/qxcbnativeinterface.h

index f9ddd1f..626f6a1 100644 (file)
@@ -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
index 47e2f82..579a0bc 100644 (file)
@@ -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);
 };
index afc6c18..230ce89 100644 (file)
 #include "qxcbclipboard.h"
 #include "qxcbdrag.h"
 #include "qxcbwmsupport.h"
+#include "qxcbnativeinterface.h"
 
 #include <QtAlgorithms>
 #include <QSocketNotifier>
 #include <QAbstractEventDispatcher>
 #include <QTimer>
+#include <QByteArray>
 
 #include <stdio.h>
 #include <errno.h>
@@ -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) {
index 1feba55..a02acec 100644 (file)
@@ -66,6 +66,7 @@ class QXcbDrag;
 class QXcbKeyboard;
 class QXcbClipboard;
 class QXcbWMSupport;
+class QXcbNativeInterface;
 
 typedef QHash<xcb_window_t, QXcbWindow *> 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<QXcbConnection *>(this); }
@@ -390,6 +391,7 @@ private:
     QXcbClipboard *m_clipboard;
     QXcbDrag *m_drag;
     QScopedPointer<QXcbWMSupport> m_wmSupport;
+    QXcbNativeInterface *m_nativeInterface;
 
 #if defined(XCB_USE_XLIB)
     void *m_xlib_display;
index 3cf50cb..418915b 100644 (file)
@@ -90,13 +90,14 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
 #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 &parameters)
             screenAdded(screen);
 
     m_fontDatabase.reset(new QGenericUnixFontDatabase());
-    m_nativeInterface.reset(new QXcbNativeInterface);
     m_inputContext.reset(QPlatformInputContextFactory::create());
     m_accessibility.reset(new QPlatformAccessibility());
 }
index 8a3926d..2bb5f1e 100644 (file)
@@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE
 
 class QXcbConnection;
 class QAbstractEventDispatcher;
+class QXcbNativeInterface;
 
 class QXcbIntegration : public QPlatformIntegration
 {
@@ -80,7 +81,7 @@ private:
     QList<QXcbConnection *> m_connections;
 
     QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
-    QScopedPointer<QPlatformNativeInterface> m_nativeInterface;
+    QScopedPointer<QXcbNativeInterface> m_nativeInterface;
 
     QScopedPointer<QPlatformInputContext> m_inputContext;
     QAbstractEventDispatcher *m_eventDispatcher;
index 52ff309..535d66a 100644 (file)
@@ -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;
index 517e92b..fae2a3c 100644 (file)
@@ -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<QByteArray, EventFilter> m_eventFilters;
+
     static QXcbScreen *qPlatformScreenForWindow(QWindow *window);
 };