diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 0597b18679..10a8f26614 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -391,28 +391,36 @@ QXcbConnection::~QXcbConnection() delete m_keyboard; } -void QXcbConnection::addWindow(xcb_window_t id, QXcbWindow *window) +void QXcbConnection::addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener) { - m_mapper.insert(id, window); + m_mapper.insert(id, eventListener); } -void QXcbConnection::removeWindow(xcb_window_t id) +void QXcbConnection::removeWindowEventListener(xcb_window_t id) { m_mapper.remove(id); } -QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id) +QXcbWindowEventListener *QXcbConnection::windowEventListenerFromId(xcb_window_t id) { return m_mapper.value(id, 0); } +QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id) +{ + QXcbWindowEventListener *listener = m_mapper.value(id, 0); + if (listener) + return listener->toWindow(); + return 0; +} + #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \ { \ event_t *e = (event_t *)event; \ - if (QXcbWindow *platformWindow = platformWindowFromId(e->windowMember)) { \ - handled = QWindowSystemInterface::handleNativeEvent(platformWindow->window(), m_nativeInterface->genericEventFilterType(), event, &result); \ + if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \ + handled = eventListener->handleGenericEvent(event, &result); \ if (!handled) \ - platformWindow->handler(e); \ + eventListener->handler(e); \ } \ } \ break; @@ -420,10 +428,10 @@ break; #define HANDLE_KEYBOARD_EVENT(event_t, handler) \ { \ event_t *e = (event_t *)event; \ - if (QXcbWindow *platformWindow = platformWindowFromId(e->event)) { \ - handled = QWindowSystemInterface::handleNativeEvent(platformWindow->window(), m_nativeInterface->genericEventFilterType(), event, &result); \ + if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \ + handled = eventListener->handleGenericEvent(event, &result); \ if (!handled) \ - m_keyboard->handler(m_focusWindow ? m_focusWindow : platformWindow, e); \ + m_keyboard->handler(m_focusWindow ? m_focusWindow : eventListener, e); \ } \ } \ break; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 27de5a4e83..44c0e28dd5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -80,8 +80,6 @@ class QXcbClipboard; class QXcbWMSupport; class QXcbNativeInterface; -typedef QHash WindowMapper; - namespace QXcbAtom { enum Atom { // window-manager <-> client protocols @@ -301,6 +299,30 @@ private: XcbPollForQueuedEventFunctionPointer m_xcb_poll_for_queued_event; }; +class QXcbWindowEventListener +{ +public: + virtual bool handleGenericEvent(xcb_generic_event_t *, long *) { return false; } + + virtual void handleExposeEvent(const xcb_expose_event_t *) {} + virtual void handleClientMessageEvent(const xcb_client_message_event_t *) {} + virtual void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *) {} + virtual void handleMapNotifyEvent(const xcb_map_notify_event_t *) {} + virtual void handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *) {} + virtual void handleButtonPressEvent(const xcb_button_press_event_t *) {} + virtual void handleButtonReleaseEvent(const xcb_button_release_event_t *) {} + virtual void handleMotionNotifyEvent(const xcb_motion_notify_event_t *) {} + virtual void handleEnterNotifyEvent(const xcb_enter_notify_event_t *) {} + virtual void handleLeaveNotifyEvent(const xcb_leave_notify_event_t *) {} + virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {} + virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {} + virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {} + + virtual QXcbWindow *toWindow() { return 0; } +}; + +typedef QHash WindowMapper; + class QAbstractEventDispatcher; class QXcbConnection : public QObject { @@ -356,8 +378,9 @@ public: void handleXcbError(xcb_generic_error_t *error); void handleXcbEvent(xcb_generic_event_t *event); - void addWindow(xcb_window_t id, QXcbWindow *window); - void removeWindow(xcb_window_t id); + void addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener); + void removeWindowEventListener(xcb_window_t id); + QXcbWindowEventListener *windowEventListenerFromId(xcb_window_t id); QXcbWindow *platformWindowFromId(xcb_window_t id); xcb_generic_event_t *checkEvent(int type); @@ -393,6 +416,8 @@ public: void grabServer(); void ungrabServer(); + + QXcbNativeInterface *nativeInterface() const { return m_nativeInterface; } private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 4ac60f6077..51c400ed9c 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -1172,14 +1172,20 @@ xcb_keysym_t QXcbKeyboard::lookupString(QWindow *window, uint state, xcb_keycode #endif } -void QXcbKeyboard::handleKeyPressEvent(QXcbWindow *window, const xcb_key_press_event_t *event) +void QXcbKeyboard::handleKeyPressEvent(QXcbWindowEventListener *eventListener, const xcb_key_press_event_t *event) { + QXcbWindow *window = eventListener->toWindow(); + if (!window) + return; window->updateNetWmUserTime(event->time); handleKeyEvent(window->window(), QEvent::KeyPress, event->detail, event->state, event->time); } -void QXcbKeyboard::handleKeyReleaseEvent(QXcbWindow *window, const xcb_key_release_event_t *event) +void QXcbKeyboard::handleKeyReleaseEvent(QXcbWindowEventListener *eventListener, const xcb_key_release_event_t *event) { + QXcbWindow *window = eventListener->toWindow(); + if (!window) + return; handleKeyEvent(window->window(), QEvent::KeyRelease, event->detail, event->state, event->time); } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index da25c51107..3c71daa57f 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -58,8 +58,8 @@ public: QXcbKeyboard(QXcbConnection *connection); ~QXcbKeyboard(); - void handleKeyPressEvent(QXcbWindow *window, const xcb_key_press_event_t *event); - void handleKeyReleaseEvent(QXcbWindow *window, const xcb_key_release_event_t *event); + void handleKeyPressEvent(QXcbWindowEventListener *eventListener, const xcb_key_press_event_t *event); + void handleKeyReleaseEvent(QXcbWindowEventListener *eventListener, const xcb_key_release_event_t *event); void handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 7d6d6a94b3..c845b875bf 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -53,6 +53,7 @@ #include "qxcbkeyboard.h" #include "qxcbwmsupport.h" #include "qxcbimage.h" +#include "qxcbnativeinterface.h" #include @@ -224,7 +225,7 @@ void QXcbWindow::create() m_window = m_screen->root(); m_depth = m_screen->screen()->root_depth; m_imageFormat = imageFormatForDepth(m_depth); - connection()->addWindow(m_window, this); + connection()->addWindowEventListener(m_window, this); return; } @@ -347,7 +348,7 @@ void QXcbWindow::create() 0)); // value list } - connection()->addWindow(m_window, this); + connection()->addWindowEventListener(m_window, this); Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); @@ -481,7 +482,7 @@ void QXcbWindow::destroy() xcb_destroy_window(xcb_connection(), m_netWmUserTimeWindow); m_netWmUserTimeWindow = XCB_NONE; } - connection()->removeWindow(m_window); + connection()->removeWindowEventListener(m_window); Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window)); m_window = 0; } @@ -1447,6 +1448,14 @@ private: bool m_pending; }; +bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) +{ + return QWindowSystemInterface::handleNativeEvent(window(), + connection()->nativeInterface()->genericEventFilterType(), + event, + result); +} + void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) { QRect rect(event->x, event->y, event->width, event->height); @@ -1682,6 +1691,8 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) handleMouseEvent(event->time, local, global, modifiers); } +QXcbWindow *QXcbWindow::toWindow() { return this; } + void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers) { connection()->setTime(time); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 300596845e..5601a115e9 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE class QXcbScreen; class QXcbEGLSurface; class QIcon; -class QXcbWindow : public QXcbObject, public QPlatformWindow +class QXcbWindow : public QXcbObject, public QXcbWindowEventListener, public QPlatformWindow { public: enum NetWmState { @@ -126,20 +126,24 @@ public: uint depth() const { return m_depth; } QImage::Format imageFormat() const { return m_imageFormat; } - void handleExposeEvent(const xcb_expose_event_t *event); - void handleClientMessageEvent(const xcb_client_message_event_t *event); - void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event); - void handleMapNotifyEvent(const xcb_map_notify_event_t *event); - void handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event); - void handleButtonPressEvent(const xcb_button_press_event_t *event); - void handleButtonReleaseEvent(const xcb_button_release_event_t *event); - void handleMotionNotifyEvent(const xcb_motion_notify_event_t *event); + bool handleGenericEvent(xcb_generic_event_t *event, long *result) Q_DECL_OVERRIDE; - void handleEnterNotifyEvent(const xcb_enter_notify_event_t *event); - void handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event); - void handleFocusInEvent(const xcb_focus_in_event_t *event); - void handleFocusOutEvent(const xcb_focus_out_event_t *event); - void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event); + void handleExposeEvent(const xcb_expose_event_t *event) Q_DECL_OVERRIDE; + void handleClientMessageEvent(const xcb_client_message_event_t *event) Q_DECL_OVERRIDE; + void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event) Q_DECL_OVERRIDE; + void handleMapNotifyEvent(const xcb_map_notify_event_t *event) Q_DECL_OVERRIDE; + void handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) Q_DECL_OVERRIDE; + void handleButtonPressEvent(const xcb_button_press_event_t *event) Q_DECL_OVERRIDE; + void handleButtonReleaseEvent(const xcb_button_release_event_t *event) Q_DECL_OVERRIDE; + void handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) Q_DECL_OVERRIDE; + + void handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) Q_DECL_OVERRIDE; + void handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event) Q_DECL_OVERRIDE; + void handleFocusInEvent(const xcb_focus_in_event_t *event) Q_DECL_OVERRIDE; + void handleFocusOutEvent(const xcb_focus_out_event_t *event) Q_DECL_OVERRIDE; + void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE; + + QXcbWindow *toWindow() Q_DECL_OVERRIDE; void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers);