Add QXcbWindowEventListener

This makes it possible to listen for events on xcb_window_t which are
not platformwindows inside the xcb plugin

Change-Id: Ic9ec17ed757a7f9a5302ef2759c119a72bac573c
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
This commit is contained in:
Jørgen Lind 2013-04-26 08:39:20 +02:00 committed by The Qt Project
parent 7288625c52
commit fca94fa5ed
6 changed files with 89 additions and 35 deletions

View File

@ -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;

View File

@ -80,8 +80,6 @@ class QXcbClipboard;
class QXcbWMSupport;
class QXcbNativeInterface;
typedef QHash<xcb_window_t, QXcbWindow *> 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<xcb_window_t, QXcbWindowEventListener *> 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();

View File

@ -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);
}

View File

@ -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);

View File

@ -53,6 +53,7 @@
#include "qxcbkeyboard.h"
#include "qxcbwmsupport.h"
#include "qxcbimage.h"
#include "qxcbnativeinterface.h"
#include <qpa/qplatformintegration.h>
@ -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);

View File

@ -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);