summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2012-03-14 17:55:43 +0100
committerQt by Nokia <qt-info@nokia.com>2012-03-22 11:43:36 +0100
commit55fa3c189f88933d390177ad5606d3de9deacf93 (patch)
treea8c96bead830fa88de6bee2783b6eba3591bb014
parent9c7cdce672df7da5c84b0ae6ca10ff09a670a315 (diff)
Got rid of Map / Unmap events in favor of Expose event.
Since change 2e4d8f67a871f2033 the need for Map and Unmap events has gone away, as now the Expose event is used to notify the application about when it can start rendering. The Map and Unmap events weren't really used except by QWidget to set the WA_Mapped flag, which we now set based on the expose / unexpose. Also guarantee that a Resize event is always sent before the first Expose, by re-introducing an asynchronous expose event handler. Since an expose is required before rendering to a QWindow, show a warning if QOpenGLContext::swapBuffers() or QBackingStore::flush() if called on a window that has not received its first expose. Change-Id: Ia6b609aa275d5b463b5011a96f2fd9bbe52e9bc4 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
-rw-r--r--examples/qpa/windows/window.cpp14
-rw-r--r--src/corelib/kernel/qcoreevent.h13
-rw-r--r--src/gui/kernel/qguiapplication.cpp38
-rw-r--r--src/gui/kernel/qguiapplication_p.h3
-rw-r--r--src/gui/kernel/qopenglcontext.cpp9
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.cpp6
-rw-r--r--src/gui/kernel/qwindow.cpp36
-rw-r--r--src/gui/kernel/qwindow_p.h5
-rw-r--r--src/gui/kernel/qwindowsysteminterface_qpa.cpp20
-rw-r--r--src/gui/kernel/qwindowsysteminterface_qpa.h4
-rw-r--r--src/gui/kernel/qwindowsysteminterface_qpa_p.h24
-rw-r--r--src/gui/painting/qbackingstore.cpp4
-rw-r--r--src/opengl/qgl.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp23
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h4
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp11
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp27
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa.cpp17
-rw-r--r--tests/auto/gui/kernel/kernel.pro1
-rw-r--r--tests/auto/gui/kernel/qbackingstore/qbackingstore.pro9
-rw-r--r--tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp103
-rw-r--r--tests/auto/gui/kernel/qwindow/qwindow.pro1
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp58
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp15
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp32
26 files changed, 321 insertions, 163 deletions
diff --git a/examples/qpa/windows/window.cpp b/examples/qpa/windows/window.cpp
index 3ea2f61600..f0eba15cbf 100644
--- a/examples/qpa/windows/window.cpp
+++ b/examples/qpa/windows/window.cpp
@@ -103,9 +103,9 @@ void Window::mouseMoveEvent(QMouseEvent *event)
p.setRenderHint(QPainter::Antialiasing);
p.drawLine(m_lastPos, event->pos());
m_lastPos = event->pos();
- }
- scheduleRender();
+ scheduleRender();
+ }
}
void Window::mouseReleaseEvent(QMouseEvent *event)
@@ -115,9 +115,9 @@ void Window::mouseReleaseEvent(QMouseEvent *event)
p.setRenderHint(QPainter::Antialiasing);
p.drawLine(m_lastPos, event->pos());
m_lastPos = QPoint(-1, -1);
- }
- scheduleRender();
+ scheduleRender();
+ }
}
void Window::exposeEvent(QExposeEvent *)
@@ -139,8 +139,7 @@ void Window::resizeEvent(QResizeEvent *)
QPainter p(&m_image);
p.drawImage(0, 0, old);
}
-
- render();
+ scheduleRender();
}
void Window::keyPressEvent(QKeyEvent *event)
@@ -168,7 +167,8 @@ void Window::scheduleRender()
void Window::timerEvent(QTimerEvent *)
{
- render();
+ if (isExposed())
+ render();
killTimer(m_renderTimer);
m_renderTimer = 0;
}
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 1d54b32dfa..a207849604 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -268,17 +268,14 @@ public:
ScrollPrepare = 204,
Scroll = 205,
- Map = 206,
- Unmap = 207,
+ Expose = 206,
- Expose = 208,
+ InputMethodQuery = 207,
+ OrientationChange = 208, // Screen orientation has changed
- InputMethodQuery = 209,
- OrientationChange = 210, // Screen orientation has changed
+ TouchCancel = 209,
- TouchCancel = 211,
-
- ThemeChange = 212,
+ ThemeChange = 210,
// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index c6ff5bb230..0fd18e7d2d 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -971,12 +971,6 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
QGuiApplicationPrivate::processThemeChanged(
static_cast<QWindowSystemInterfacePrivate::ThemeChangeEvent *>(e));
break;
- case QWindowSystemInterfacePrivate::Map:
- QGuiApplicationPrivate::processMapEvent(static_cast<QWindowSystemInterfacePrivate::MapEvent *>(e));
- break;
- case QWindowSystemInterfacePrivate::Unmap:
- QGuiApplicationPrivate::processUnmapEvent(static_cast<QWindowSystemInterfacePrivate::UnmapEvent *>(e));
- break;
case QWindowSystemInterfacePrivate::Expose:
QGuiApplicationPrivate::processExposeEvent(static_cast<QWindowSystemInterfacePrivate::ExposeEvent *>(e));
break;
@@ -1589,30 +1583,28 @@ void QGuiApplicationPrivate::reportLogicalDotsPerInchChange(QWindowSystemInterfa
emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch());
}
-void QGuiApplicationPrivate::processMapEvent(QWindowSystemInterfacePrivate::MapEvent *e)
+void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e)
{
- if (!e->mapped)
+ if (!e->exposed)
return;
- QEvent event(QEvent::Map);
- QCoreApplication::sendSpontaneousEvent(e->mapped.data(), &event);
-}
+ QWindow *window = e->exposed.data();
+ QWindowPrivate *p = qt_window_private(window);
-void QGuiApplicationPrivate::processUnmapEvent(QWindowSystemInterfacePrivate::UnmapEvent *e)
-{
- if (!e->unmapped)
- return;
+ if (!p->receivedExpose) {
+ if (p->resizeEventPending) {
+ // as a convenience for plugins, send a resize event before the first expose event if they haven't done so
+ QSize size = p->geometry.size();
+ QResizeEvent e(size, size);
+ QGuiApplication::sendSpontaneousEvent(window, &e);
- QEvent event(QEvent::Unmap);
- QCoreApplication::sendSpontaneousEvent(e->unmapped.data(), &event);
-}
+ p->resizeEventPending = false;
+ }
-void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e)
-{
- if (!e->exposed)
- return;
+ p->receivedExpose = true;
+ }
- QWindow *window = e->exposed.data();
+ p->exposed = e->isExposed;
QExposeEvent exposeEvent(e->region);
QCoreApplication::sendSpontaneousEvent(window, &exposeEvent);
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index f30a2bb5a0..6792e9382c 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -118,9 +118,6 @@ public:
static void reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e);
static void processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce);
- static void processMapEvent(QWindowSystemInterfacePrivate::MapEvent *e);
- static void processUnmapEvent(QWindowSystemInterfacePrivate::UnmapEvent *e);
-
static void processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e);
static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index eaff417f15..29f46aefd6 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -49,6 +49,7 @@
#include <QtCore/QThread>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qwindow_p.h>
#include <QtGui/QScreen>
#include <private/qopenglextensions_p.h>
@@ -502,7 +503,13 @@ void QOpenGLContext::swapBuffers(QSurface *surface)
if (surface->surfaceType() != QSurface::OpenGLSurface) {
qWarning() << "QOpenGLContext::swapBuffers() called with non-opengl surface";
return;
- }
+ }
+
+ if (surface->surfaceClass() == QSurface::Window
+ && !qt_window_private(static_cast<QWindow *>(surface))->receivedExpose)
+ {
+ qWarning() << "QOpenGLContext::swapBuffers() called with non-exposed window, behavior is undefined";
+ }
QPlatformSurface *surfaceHandle = surface->surfaceHandle();
if (!surfaceHandle)
diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp
index e12228d7bd..c8e2776366 100644
--- a/src/gui/kernel/qplatformwindow_qpa.cpp
+++ b/src/gui/kernel/qplatformwindow_qpa.cpp
@@ -142,11 +142,13 @@ QMargins QPlatformWindow::frameMargins() const
/*!
Reimplemented in subclasses to show the surface
if \a visible is \c true, and hide it if \a visible is \c false.
+
+ The default implementation sends a synchronous expose event.
*/
void QPlatformWindow::setVisible(bool visible)
{
- Q_UNUSED(visible);
- QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
+ QRect rect(QPoint(), geometry().size());
+ QWindowSystemInterface::handleSynchronousExposeEvent(window(), rect);
}
/*!
Requests setting the window flags of this surface
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 78b6f6f722..ab1e8f7601 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -108,6 +108,18 @@ QT_BEGIN_NAMESPACE
called whenever the windows exposure in the windowing system changes. On
windowing systems that do not make this information visible to the
application, isExposed() will simply return the same value as isVisible().
+
+ \section1 Rendering
+
+ There are two Qt APIs that can be used to render content into a window,
+ QBackingStore for rendering with a QPainter and flushing the contents
+ to a window with type QSurface::RasterSurface, and QOpenGLContext for
+ rendering with OpenGL to a window with type QSurface::OpenGLSurface.
+
+ The application can start rendering as soon as isExposed() returns true,
+ and can keep rendering until it isExposed() returns false. To find out when
+ isExposed() changes, reimplement exposeEvent(). The window will always get
+ a resize event before the first expose event.
*/
/*!
@@ -578,9 +590,7 @@ void QWindow::requestActivateWindow()
bool QWindow::isExposed() const
{
Q_D(const QWindow);
- if (d->platformWindow)
- return d->platformWindow->isExposed();
- return false;
+ return d->exposed;
}
/*!
@@ -1077,6 +1087,9 @@ void QWindow::destroy()
}
setVisible(false);
delete d->platformWindow;
+ d->resizeEventPending = true;
+ d->receivedExpose = false;
+ d->exposed = false;
d->platformWindow = 0;
}
@@ -1336,12 +1349,19 @@ bool QWindow::close()
The expose event is sent by the window system whenever the window's
exposure on screen changes.
+ The application can start rendering into the window with QBackingStore
+ and QOpenGLContext as soon as it gets an exposeEvent() such that
+ isExposed() is true.
+
If the window is moved off screen, is made totally obscured by another
window, iconified or similar, this function might be called and the
value of isExposed() might change to false. When this happens,
an application should stop its rendering as it is no longer visible
to the user.
+ A resize event will always be sent before the expose event the first time
+ a window is shown.
+
\sa isExposed()
*/
void QWindow::exposeEvent(QExposeEvent *ev)
@@ -1372,7 +1392,10 @@ void QWindow::resizeEvent(QResizeEvent *ev)
/*!
Override this to handle show events.
- The show event is called when the window becomes visible in the windowing system.
+ The show event is called when the window has requested becoming visible.
+
+ If the window is successfully shown by the windowing system, this will
+ be followed by a resize and an expose event.
*/
void QWindow::showEvent(QShowEvent *ev)
{
@@ -1380,9 +1403,10 @@ void QWindow::showEvent(QShowEvent *ev)
}
/*!
- Override this to handle show events.
+ Override this to handle hide evens.
- The show event is called when the window becomes hidden in the windowing system.
+ The hide event is called when the window has requested being hidden in the
+ windowing system.
*/
void QWindow::hideEvent(QHideEvent *ev)
{
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 7f3958b3ff..03b3b92a25 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -72,8 +72,10 @@ public:
, parentWindow(0)
, platformWindow(0)
, visible(false)
+ , exposed(false)
, windowState(Qt::WindowNoState)
, resizeEventPending(true)
+ , receivedExpose(false)
, positionPolicy(WindowFrameExclusive)
, contentOrientation(Qt::PrimaryOrientation)
, windowOrientation(Qt::PrimaryOrientation)
@@ -99,17 +101,18 @@ public:
return offset;
}
-
QWindow::SurfaceType surfaceType;
Qt::WindowFlags windowFlags;
QWindow *parentWindow;
QPlatformWindow *platformWindow;
bool visible;
+ bool exposed;
QSurfaceFormat requestedFormat;
QString windowTitle;
QRect geometry;
Qt::WindowState windowState;
bool resizeEventPending;
+ bool receivedExpose;
PositionPolicy positionPolicy;
Qt::ScreenOrientation contentOrientation;
Qt::ScreenOrientation windowOrientation;
diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp
index 9ab91d65d5..fcffd75b39 100644
--- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp
+++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
#include "qwindowsysteminterface_qpa.h"
+#include "qplatformwindow_qpa.h"
#include "qwindowsysteminterface_qpa_p.h"
#include "private/qguiapplication_p.h"
#include "private/qevent_p.h"
@@ -274,6 +275,15 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con
QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
}
+
+QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *exposed, const QRegion &region)
+ : WindowSystemEvent(Expose)
+ , exposed(exposed)
+ , isExposed(exposed && exposed->handle() ? exposed->handle()->isExposed() : false)
+ , region(region)
+{
+}
+
int QWindowSystemInterfacePrivate::windowSystemEventsQueued()
{
queueMutex.lock();
@@ -426,15 +436,9 @@ void QWindowSystemInterface::handleThemeChange(QWindow *tlw)
QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
}
-void QWindowSystemInterface::handleMapEvent(QWindow *tlw)
-{
- QWindowSystemInterfacePrivate::MapEvent *e = new QWindowSystemInterfacePrivate::MapEvent(tlw);
- QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
-}
-
-void QWindowSystemInterface::handleUnmapEvent(QWindow *tlw)
+void QWindowSystemInterface::handleExposeEvent(QWindow *tlw, const QRegion &region)
{
- QWindowSystemInterfacePrivate::UnmapEvent *e = new QWindowSystemInterfacePrivate::UnmapEvent(tlw);
+ QWindowSystemInterfacePrivate::ExposeEvent *e = new QWindowSystemInterfacePrivate::ExposeEvent(tlw, region);
QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
}
diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h
index 560f47d972..1fbf430bf9 100644
--- a/src/gui/kernel/qwindowsysteminterface_qpa.h
+++ b/src/gui/kernel/qwindowsysteminterface_qpa.h
@@ -130,9 +130,7 @@ public:
static void handleWindowActivated(QWindow *w);
static void handleWindowStateChanged(QWindow *w, Qt::WindowState newState);
- static void handleMapEvent(QWindow *w);
- static void handleUnmapEvent(QWindow *w);
-
+ static void handleExposeEvent(QWindow *tlw, const QRegion &region);
static void handleSynchronousExposeEvent(QWindow *tlw, const QRegion &region);
// Drag and drop. These events are sent immediately.
diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h
index fe97b486ad..d7be7699e9 100644
--- a/src/gui/kernel/qwindowsysteminterface_qpa_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h
@@ -42,6 +42,7 @@
#define QWINDOWSYSTEMINTERFACE_QPA_P_H
#include "qwindowsysteminterface_qpa.h"
+
#include <QElapsedTimer>
QT_BEGIN_HEADER
@@ -66,8 +67,6 @@ public:
ScreenAvailableGeometry,
ScreenLogicalDotsPerInch,
ThemeChange,
- Map,
- Unmap,
Expose
};
@@ -241,28 +240,11 @@ public:
QWeakPointer<QWindow> window;
};
- class MapEvent : public WindowSystemEvent {
- public:
- MapEvent(QWindow *mapped)
- : WindowSystemEvent(Map), mapped(mapped)
- { }
- QWeakPointer<QWindow> mapped;
- };
-
- class UnmapEvent : public WindowSystemEvent {
- public:
- UnmapEvent(QWindow *unmapped)
- : WindowSystemEvent(Unmap), unmapped(unmapped)
- { }
- QWeakPointer<QWindow> unmapped;
- };
-
class ExposeEvent : public WindowSystemEvent {
public:
- ExposeEvent(QWindow *exposed, const QRegion &region)
- : WindowSystemEvent(Expose), exposed(exposed), region(region)
- { }
+ ExposeEvent(QWindow *exposed, const QRegion &region);
QWeakPointer<QWindow> exposed;
+ bool isExposed;
QRegion region;
};
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 03c2fc8d6a..63f7ba594f 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -82,6 +82,10 @@ void QBackingStore::flush(const QRegion &region, QWindow *win, const QPoint &off
{
if (!win)
win = window();
+
+ if (win && !qt_window_private(win)->receivedExpose)
+ qWarning("QBackingStore::flush() called with non-exposed window, behavior is undefined");
+
d_ptr->platformBackingStore->flush(win, region, offset);
}
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index eb27e865b5..2c683f7ae7 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -3770,7 +3770,7 @@ void QGLWidget::setFormat(const QGLFormat &format)
void QGLWidget::updateGL()
{
- if (updatesEnabled())
+ if (updatesEnabled() && testAttribute(Qt::WA_Mapped))
glDraw();
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index fa3661db22..6ff854805c 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -708,7 +708,6 @@ void QWindowsWindow::setVisible(bool visible)
hide_sys();
}
}
- QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
bool QWindowsWindow::isVisible() const
@@ -804,12 +803,12 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
void QWindowsWindow::handleShown()
{
- QWindowSystemInterface::handleMapEvent(window());
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
}
void QWindowsWindow::handleHidden()
{
- QWindowSystemInterface::handleUnmapEvent(window());
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion());
}
void QWindowsWindow::setGeometry(const QRect &rectIn)
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 4de3734c22..3e63ab0f27 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -160,6 +160,8 @@ void QXcbWindow::create()
{
destroy();
+ m_deferredExpose = false;
+ m_configureNotifyPending = true;
m_windowState = Qt::WindowNoState;
Qt::WindowType type = window()->windowType();
@@ -1260,7 +1262,7 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
// if count is non-zero there are more expose events pending
if (event->count == 0) {
- QWindowSystemInterface::handleSynchronousExposeEvent(window(), m_exposeRegion);
+ QWindowSystemInterface::handleExposeEvent(window(), m_exposeRegion);
m_exposeRegion = QRegion();
}
}
@@ -1327,6 +1329,13 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
+ m_configureNotifyPending = false;
+
+ if (m_deferredExpose) {
+ m_deferredExpose = false;
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
+ }
+
m_dirtyFrameMargins = true;
#if XCB_USE_DRI2
@@ -1335,13 +1344,21 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
#endif
}
+bool QXcbWindow::isExposed() const
+{
+ return m_mapped;
+}
+
void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
{
if (event->window == m_window) {
m_mapped = true;
if (m_deferredActivation)
requestActivateWindow();
- QWindowSystemInterface::handleMapEvent(window());
+ if (m_configureNotifyPending)
+ m_deferredExpose = true;
+ else
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
}
@@ -1349,7 +1366,7 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
{
if (event->window == m_window) {
m_mapped = false;
- QWindowSystemInterface::handleUnmapEvent(window());
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion());
}
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index c212095e98..37e0bdb8d3 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -72,6 +72,8 @@ public:
WId winId() const;
void setParent(const QPlatformWindow *window);
+ bool isExposed() const;
+
void setWindowTitle(const QString &title);
void raise();
void lower();
@@ -155,6 +157,8 @@ private:
bool m_mapped;
bool m_transparent;
bool m_deferredActivation;
+ bool m_deferredExpose;
+ bool m_configureNotifyPending;
xcb_window_t m_netWmUserTimeWindow;
QSurfaceFormat m_format;
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index 3d23b04ddf..0f55646958 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -440,9 +440,9 @@ static inline QRect positionTopLevelWindow(QRect geometry, const QScreen *screen
void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
- q->setAttribute(Qt::WA_Mapped);
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
invalidateBuffer(q->rect());
+ q->setAttribute(Qt::WA_Mapped);
return;
}
@@ -483,8 +483,8 @@ void QWidgetPrivate::show_sys()
void QWidgetPrivate::hide_sys()
{
Q_Q(QWidget);
- q->setAttribute(Qt::WA_Mapped, false);
deactivateWidgetCleanup();
+
if (!q->isWindow()) {
QWidget *p = q->parentWidget();
if (p &&p->isVisible()) {
@@ -492,7 +492,12 @@ void QWidgetPrivate::hide_sys()
}
return;
}
- if (QWindow *window = q->windowHandle()) {
+
+ invalidateBuffer(q->rect());
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ q->setAttribute(Qt::WA_Mapped, false);
+ } else if (QWindow *window = q->windowHandle()) {
window->setVisible(false);
}
}
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index b331356e66..2e9f072a0f 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -914,29 +914,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
{
- if (!tlw || !tlwExtra)
- return true;
-
-#ifdef Q_WS_X11
- // Delay the sync until we get an Expose event from X11 (initial show).
- // Qt::WA_Mapped is set to true, but the actual mapping has not yet occurred.
- // However, we must repaint immediately regardless of the state if someone calls repaint().
- if (tlwExtra->waitingForMapNotify && !tlwExtra->inRepaint)
- return true;
-#endif
-
- if (!tlw->testAttribute(Qt::WA_Mapped))
- return true;
-
- if (!tlw->isVisible()
-#ifndef Q_WS_X11
- // If we're minimized on X11, WA_Mapped will be false and we
- // will return in the case above. Some window managers on X11
- // sends us the PropertyNotify to change the minimized state
- // *AFTER* we've received the expose event, which is baaad.
- || tlw->isMinimized()
-#endif
- )
+ if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible())
return true;
return false;
@@ -1345,6 +1323,9 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn)
return;
Q_Q(QWidget);
+ if (discardSyncRequest(q, maybeTopData()))
+ return;
+
if (q->testAttribute(Qt::WA_StaticContents)) {
if (!extra)
createExtra();
diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp
index f58dddb70f..498908f4db 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa.cpp
+++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp
@@ -137,15 +137,6 @@ bool QWidgetWindow::event(QEvent *event)
handleDragEvent(event);
break;
- case QEvent::Map:
- m_widget->setAttribute(Qt::WA_Mapped);
- m_widget->d_func()->syncBackingStore();
- return true;
-
- case QEvent::Unmap:
- m_widget->setAttribute(Qt::WA_Mapped, false);
- return true;
-
case QEvent::Expose:
handleExposeEvent(static_cast<QExposeEvent *>(event));
return true;
@@ -432,7 +423,13 @@ void QWidgetWindow::handleDragEvent(QEvent *event)
void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
{
- m_widget->d_func()->syncBackingStore(event->region());
+ if (isExposed()) {
+ m_widget->setAttribute(Qt::WA_Mapped);
+ if (!event->region().isNull())
+ m_widget->d_func()->syncBackingStore(event->region());
+ } else {
+ m_widget->setAttribute(Qt::WA_Mapped, false);
+ }
}
void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro
index 48d94b9bf8..0bd988b68c 100644
--- a/tests/auto/gui/kernel/kernel.pro
+++ b/tests/auto/gui/kernel/kernel.pro
@@ -1,5 +1,6 @@
TEMPLATE=subdirs
SUBDIRS=\
+ qbackingstore \
qclipboard \
qdrag \
qevent \
diff --git a/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro b/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro
new file mode 100644
index 0000000000..cc0a2c69f7
--- /dev/null
+++ b/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qbackingstore
+
+QT += core-private gui-private testlib
+
+SOURCES += tst_qbackingstore.cpp
+
+mac: CONFIG += insignificant_test # QTBUG-23059
+win32: CONFIG += insignificant_test # QTBUG-24885
diff --git a/tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp b/tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp
new file mode 100644
index 0000000000..678e616b19
--- /dev/null
+++ b/tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qwindow.h>
+#include <qbackingstore.h>
+#include <qpainter.h>
+
+#include <QtTest/QtTest>
+
+#include <QEvent>
+
+// For QSignalSpy slot connections.
+Q_DECLARE_METATYPE(Qt::ScreenOrientation)
+
+class tst_QBackingStore : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void flush();
+};
+
+class Window : public QWindow
+{
+public:
+ Window()
+ : backingStore(this)
+ {
+ }
+
+ void resizeEvent(QResizeEvent *)
+ {
+ backingStore.resize(size());
+ }
+
+ void exposeEvent(QExposeEvent *event)
+ {
+ QRect rect(QPoint(), size());
+
+ backingStore.beginPaint(rect);
+
+ QPainter p(backingStore.paintDevice());
+ p.fillRect(rect, Qt::white);
+ p.end();
+
+ backingStore.endPaint();
+
+ backingStore.flush(event->region().boundingRect());
+ }
+
+private:
+ QBackingStore backingStore;
+};
+
+void tst_QBackingStore::flush()
+{
+ Window window;
+ window.setGeometry(20, 20, 200, 200);
+ window.showMaximized();
+
+ QTRY_VERIFY(window.isExposed());
+}
+
+#include <tst_qbackingstore.moc>
+QTEST_MAIN(tst_QBackingStore);
diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro
index 363f7dd92e..fb8132afab 100644
--- a/tests/auto/gui/kernel/qwindow/qwindow.pro
+++ b/tests/auto/gui/kernel/qwindow/qwindow.pro
@@ -6,4 +6,5 @@ QT += core-private gui-private testlib
SOURCES += tst_qwindow.cpp
mac: CONFIG += insignificant_test # QTBUG-23059
+win32: CONFIG += insignificant_test # QTBUG-24904
diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
index f4556f7e32..ebd8823149 100644
--- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
+++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
@@ -53,8 +53,10 @@ class tst_QWindow: public QObject
Q_OBJECT
private slots:
+ void eventOrderOnShow();
void mapGlobal();
void positioning();
+ void isExposed();
void isActive();
void testInputEvents();
void touchToMouseTranslation();
@@ -114,6 +116,7 @@ public:
bool event(QEvent *event)
{
m_received[event->type()]++;
+ m_order << event->type();
return QWindow::event(event);
}
@@ -123,10 +126,32 @@ public:
return m_received.value(type, 0);
}
+ int eventIndex(QEvent::Type type)
+ {
+ return m_order.indexOf(type);
+ }
+
private:
QHash<QEvent::Type, int> m_received;
+ QVector<QEvent::Type> m_order;
};
+void tst_QWindow::eventOrderOnShow()
+{
+ QRect geometry(80, 80, 40, 40);
+
+ Window window;
+ window.setGeometry(geometry);
+ window.show();
+
+ QTRY_COMPARE(window.received(QEvent::Show), 1);
+ QTRY_COMPARE(window.received(QEvent::Resize), 1);
+ QTRY_VERIFY(window.isExposed());
+
+ QVERIFY(window.eventIndex(QEvent::Show) < window.eventIndex(QEvent::Resize));
+ QVERIFY(window.eventIndex(QEvent::Resize) < window.eventIndex(QEvent::Expose));
+}
+
void tst_QWindow::positioning()
{
QRect geometry(80, 80, 40, 40);
@@ -137,7 +162,7 @@ void tst_QWindow::positioning()
window.show();
QTRY_COMPARE(window.received(QEvent::Resize), 1);
- QTRY_COMPARE(window.received(QEvent::Map), 1);
+ QTRY_VERIFY(window.received(QEvent::Expose) > 0);
QMargins originalMargins = window.frameMargins();
@@ -148,6 +173,9 @@ void tst_QWindow::positioning()
QPoint originalFramePos = window.framePos();
window.setWindowState(Qt::WindowFullScreen);
+#ifdef Q_OS_WIN
+ QEXPECT_FAIL("", "QTBUG-24904 - Too many resize events on setting window state", Continue);
+#endif
QTRY_COMPARE(window.received(QEvent::Resize), 2);
window.setWindowState(Qt::WindowNoState);
@@ -179,13 +207,32 @@ void tst_QWindow::positioning()
}
}
+void tst_QWindow::isExposed()
+{
+ QRect geometry(80, 80, 40, 40);
+
+ Window window;
+ window.setGeometry(geometry);
+ QCOMPARE(window.geometry(), geometry);
+ window.show();
+
+ QTRY_VERIFY(window.received(QEvent::Expose) > 0);
+ QTRY_VERIFY(window.isExposed());
+
+ window.hide();
+
+ QTRY_VERIFY(window.received(QEvent::Expose) > 1);
+ QTRY_VERIFY(!window.isExposed());
+}
+
+
void tst_QWindow::isActive()
{
Window window;
window.setGeometry(80, 80, 40, 40);
window.show();
- QTRY_COMPARE(window.received(QEvent::Map), 1);
+ QTRY_VERIFY(window.isExposed());
QTRY_COMPARE(window.received(QEvent::Resize), 1);
QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
QVERIFY(window.isActive());
@@ -195,15 +242,14 @@ void tst_QWindow::isActive()
child.setGeometry(10, 10, 20, 20);
child.show();
- QTRY_COMPARE(child.received(QEvent::Map), 1);
+ QTRY_VERIFY(child.isExposed());
child.requestActivateWindow();
QTRY_VERIFY(QGuiApplication::focusWindow() == &child);
QVERIFY(child.isActive());
- // parent shouldn't receive new map or resize events from child being shown
- QTRY_COMPARE(window.received(QEvent::Map), 1);
+ // parent shouldn't receive new resize events from child being shown
QTRY_COMPARE(window.received(QEvent::Resize), 1);
QTRY_COMPARE(window.received(QEvent::FocusIn), 1);
QTRY_COMPARE(window.received(QEvent::FocusOut), 1);
@@ -219,7 +265,7 @@ void tst_QWindow::isActive()
dialog.requestActivateWindow();
- QTRY_COMPARE(dialog.received(QEvent::Map), 1);
+ QTRY_VERIFY(dialog.isExposed());
QTRY_COMPARE(dialog.received(QEvent::Resize), 1);
QTRY_VERIFY(QGuiApplication::focusWindow() == &dialog);
QVERIFY(dialog.isActive());
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
index 98c3866dd2..639a1f61a9 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -11116,20 +11116,23 @@ void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
view.showFullScreen();
else
view.show();
- QTest::qWaitForWindowShown(&view);
- QEXPECT_FAIL("", "QTBUG-22434", Abort);
- QTRY_COMPARE(view.repaints, 1);
- QTRY_COMPARE(item->painted, 1);
+ QTest::qWaitForWindowShown(view.windowHandle());
+ view.activateWindow();
+ QTRY_VERIFY(view.isActiveWindow());
+ QTRY_VERIFY(view.repaints >= 1);
+ int count = view.repaints;
+ QTRY_COMPARE(item->painted, count);
+ // cached as graphics effects, not painted multiple times
QTRY_COMPARE(item2->painted, 1);
QTRY_COMPARE(item3->painted, 1);
item2->update();
QApplication::processEvents();
- QTRY_COMPARE(item->painted, 2);
+ QTRY_COMPARE(item->painted, count + 1);
QTRY_COMPARE(item2->painted, 2);
QTRY_COMPARE(item3->painted, 2);
item2->update();
QApplication::processEvents();
- QTRY_COMPARE(item->painted, 3);
+ QTRY_COMPARE(item->painted, count + 2);
QTRY_COMPARE(item2->painted, 3);
QTRY_COMPARE(item3->painted, 3);
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
index daa06d0762..d7b1ef9199 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -1078,19 +1078,14 @@ void tst_QGraphicsScene::addItem()
CustomView view;
view.setScene(&scene);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
+ QTest::qWaitForWindowShown(view.windowHandle());
qApp->processEvents();
view.repaints = 0;
scene.addItem(path);
// Adding an item should always issue a repaint.
- qApp->processEvents(); // <- delayed update is called
- qApp->processEvents(); // <- scene schedules pending update
- qApp->processEvents(); // <- pending update is sent to view
- QVERIFY(view.repaints > 0);
+ QTRY_VERIFY(view.repaints > 0);
view.repaints = 0;
QCOMPARE(scene.itemAt(0, 0), path);
@@ -1103,10 +1098,7 @@ void tst_QGraphicsScene::addItem()
scene.addItem(path2);
// Adding an item should always issue a repaint.
- qApp->processEvents(); // <- delayed update is called
- qApp->processEvents(); // <- scene schedules pending update
- qApp->processEvents(); // <- pending update is sent to view
- QVERIFY(view.repaints > 0);
+ QTRY_VERIFY(view.repaints > 0);
QCOMPARE(scene.itemAt(100, 100), path2);
}
@@ -1285,9 +1277,7 @@ void tst_QGraphicsScene::removeItem()
QGraphicsView view(&scene);
view.setFixedSize(150, 150);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
+ QTest::qWaitForWindowShown(view.windowHandle());
QTest::mouseMove(view.viewport(), QPoint(-1, -1));
{
QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton, 0, 0);
@@ -1615,9 +1605,7 @@ void tst_QGraphicsScene::hoverEvents_siblings()
view.rotate(10);
view.scale(1.7, 1.7);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
+ QTest::qWaitForWindowShown(view.windowHandle());
qApp->setActiveWindow(&view);
view.activateWindow();
QTest::qWait(70);
@@ -2748,11 +2736,8 @@ void tst_QGraphicsScene::contextMenuEvent()
QGraphicsView view(&scene);
view.show();
- QTest::qWaitForWindowShown(&view);
+ QTest::qWaitForWindowShown(view.windowHandle());
view.activateWindow();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
view.centerOn(item);
{
@@ -2785,10 +2770,7 @@ void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations()
QGraphicsView view(&scene, &topLevel);
view.resize(200, 200);
topLevel.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
- QTest::qWaitForWindowShown(&topLevel);
+ QTest::qWaitForWindowShown(topLevel.windowHandle());
{
QPoint pos(50, 50);