diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 98a08e9628..432f6a8cee 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -291,6 +291,11 @@ public: ScrollPrepare = 204, Scroll = 205, + Map = 206, + Unmap = 207, + + Expose = 208, + // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 731cfc97f2..a53b2c537a 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -167,6 +167,18 @@ public: QScrollEvent::ScrollState state; }; +class QExposeEvent : public QEvent +{ +public: + inline QExposeEvent(const QRegion &rgn) + : QEvent(Expose) + , region(rgn) + { + } + + QRegion region; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index cce0882a1d..bc4d2e3905 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -455,6 +455,15 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv QGuiApplicationPrivate::reportAvailableGeometryChange( static_cast(e)); break; + case QWindowSystemInterfacePrivate::Map: + QGuiApplicationPrivate::processMapEvent(static_cast(e)); + break; + case QWindowSystemInterfacePrivate::Unmap: + QGuiApplicationPrivate::processUnmapEvent(static_cast(e)); + break; + case QWindowSystemInterfacePrivate::Expose: + QGuiApplicationPrivate::processExposeEvent(static_cast(e)); + break; default: qWarning() << "Unknown user input event type:" << e->type; break; @@ -659,6 +668,24 @@ void QGuiApplicationPrivate::reportAvailableGeometryChange( return; } +void QGuiApplicationPrivate::processMapEvent(QWindowSystemInterfacePrivate::MapEvent *e) +{ + QEvent event(QEvent::Map); + QCoreApplication::sendSpontaneousEvent(e->mapped.data(), &event); +} + +void QGuiApplicationPrivate::processUnmapEvent(QWindowSystemInterfacePrivate::UnmapEvent *e) +{ + QEvent event(QEvent::Unmap); + QCoreApplication::sendSpontaneousEvent(e->unmapped.data(), &event); +} + +void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e) +{ + QExposeEvent event(e->region); + QCoreApplication::sendSpontaneousEvent(e->exposed.data(), &event); +} + #ifndef QT_NO_CLIPBOARD QClipboard * QGuiApplication::clipboard() { diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 2d0f16c2f4..c80212f8f9 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -119,6 +119,11 @@ public: static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); static void reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e); + static void processMapEvent(QWindowSystemInterfacePrivate::MapEvent *e); + static void processUnmapEvent(QWindowSystemInterfacePrivate::UnmapEvent *e); + + static void processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e); + static inline Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment) { if (!(alignment & Qt::AlignHorizontal_Mask)) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index fca8aaca46..3d227f49ca 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -49,6 +49,8 @@ #include "qwindow_p.h" #include "qguiapplication_p.h" +#include + #include QT_BEGIN_NAMESPACE @@ -486,6 +488,7 @@ void QWindow::hideEvent(QHideEvent *) bool QWindow::event(QEvent *event) { + Q_D(QWindow); switch (event->type()) { case QEvent::MouseMove: mouseMoveEvent(static_cast(event)); @@ -525,6 +528,11 @@ bool QWindow::event(QEvent *event) destroy(); break; + case QEvent::Expose: + if (d->surface) + d->surface->flush(this, static_cast(event)->region, QPoint()); + break; + default: return QObject::event(event); } diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index 6b59fb26a7..9df8b1af54 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -252,4 +252,22 @@ void QWindowSystemInterface::handleScreenCountChange(int count) QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } +void QWindowSystemInterface::handleMapEvent(QWindow *tlw) +{ + QWindowSystemInterfacePrivate::MapEvent *e = new QWindowSystemInterfacePrivate::MapEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleUnmapEvent(QWindow *tlw) +{ + QWindowSystemInterfacePrivate::UnmapEvent *e = new QWindowSystemInterfacePrivate::UnmapEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleExposeEvent(QWindow *tlw, const QRegion ®ion) +{ + QWindowSystemInterfacePrivate::ExposeEvent *e = new QWindowSystemInterfacePrivate::ExposeEvent(tlw, region); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h index 5ad4d7afb7..1188ca3439 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa.h @@ -96,6 +96,11 @@ public: static void handleLeaveEvent(QWindow *w); static void handleWindowActivated(QWindow *w); + static void handleMapEvent(QWindow *w); + static void handleUnmapEvent(QWindow *w); + + static void handleExposeEvent(QWindow *w, const QRegion ®ion); + // Changes to the screen static void handleScreenGeometryChange(int screenIndex); static void handleScreenAvailableGeometryChange(int screenIndex); diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h index 017d3b2bff..912ac877fb 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa_p.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -61,7 +61,10 @@ public: Touch, ScreenGeometry, ScreenAvailableGeometry, - ScreenCountChange + ScreenCountChange, + Map, + Unmap, + Expose }; class WindowSystemEvent { @@ -192,6 +195,31 @@ public: int index; }; + class MapEvent : public WindowSystemEvent { + public: + MapEvent(QWindow *mapped) + : WindowSystemEvent(Map), mapped(mapped) + { } + QWeakPointer mapped; + }; + + class UnmapEvent : public WindowSystemEvent { + public: + UnmapEvent(QWindow *unmapped) + : WindowSystemEvent(Unmap), unmapped(unmapped) + { } + QWeakPointer unmapped; + }; + + class ExposeEvent : public WindowSystemEvent { + public: + ExposeEvent(QWindow *exposed, const QRegion ®ion) + : WindowSystemEvent(Expose), exposed(exposed), region(region) + { } + QWeakPointer exposed; + QRegion region; + }; + static QList windowSystemEventQueue; static QMutex queueMutex; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 6acc42208d..885ec0c067 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -445,6 +445,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) 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: HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); case XCB_ENTER_NOTIFY: diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 3b70968dfc..ca86cbdb56 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -927,7 +927,7 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) if (surface) { QRect rect(event->x, event->y, event->width, event->height); - surface->flush(window(), rect, QPoint()); + QWindowSystemInterface::handleExposeEvent(window(), rect); } } @@ -981,8 +981,18 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event) { - if (event->window == m_window) + if (event->window == m_window) { m_mapped = true; + QWindowSystemInterface::handleMapEvent(window()); + } +} + +void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) +{ + if (event->window == m_window) { + m_mapped = false; + QWindowSystemInterface::handleUnmapEvent(window()); + } } static Qt::MouseButtons translateMouseButtons(int s) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 57794fda07..23b9d7ac2b 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -87,6 +87,7 @@ public: 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); diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp index dbb8112e43..786293a716 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa.cpp +++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp @@ -100,6 +100,19 @@ bool QWidgetWindow::event(QEvent *event) case QEvent::DragMove: case QEvent::Drop: handleDragEvent(event); + break; + + case QEvent::Map: + m_widget->setAttribute(Qt::WA_Mapped); + return true; + + case QEvent::Unmap: + m_widget->setAttribute(Qt::WA_Mapped, false); + return true; + + case QEvent::Expose: + handleExposeEvent(static_cast(event)); + return true; default: break; @@ -261,8 +274,19 @@ void QWidgetWindow::handleMoveEvent(QMoveEvent *event) void QWidgetWindow::handleResizeEvent(QResizeEvent *event) { + QSize oldSize = m_widget->data->crect.size(); + m_widget->data->crect = geometry(); QGuiApplication::sendSpontaneousEvent(m_widget, event); + + if (m_widget->d_func()->paintOnScreen()) { + QRegion updateRegion(geometry()); + if (m_widget->testAttribute(Qt::WA_StaticContents)) + updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); + m_widget->d_func()->syncBackingStore(updateRegion); + } else { + m_widget->d_func()->syncBackingStore(); + } } void QWidgetWindow::handleCloseEvent(QCloseEvent *) @@ -345,5 +369,9 @@ void QWidgetWindow::handleDragEvent(QEvent *event) } } +void QWidgetWindow::handleExposeEvent(QExposeEvent *event) +{ + m_widget->d_func()->syncBackingStore(event->region); +} QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h index 443123ece3..a217a969ca 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa_p.h +++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h @@ -45,6 +45,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -74,6 +75,7 @@ protected: void handleResizeEvent(QResizeEvent *); void handleWheelEvent(QWheelEvent *); void handleDragEvent(QEvent *); + void handleExposeEvent(QExposeEvent *); private: QWidget *m_widget;