Add widget support for requestUpdate() and improve its docs and tests

We must do something when requestUpdate() is called on a QWidgetWindow.
The semantics of UpdateRequest for QWindow and QWidget are unfortunately
different: for widgets an UpdateRequest means "sync the backing store".
For QWindow it also involves marking as dirty.

Change-Id: Idf40b3fc0873652dc081edeb12c96b3007a126ef
Reviewed-by: Morten Johan Sørvig <morten.sorvig@theqtcompany.com>
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
This commit is contained in:
Laszlo Agocs 2015-02-12 15:28:12 +01:00
parent 1748b7e7d2
commit effc6b4cd1
4 changed files with 64 additions and 5 deletions

View File

@ -2078,11 +2078,16 @@ void QWindowPrivate::deliverUpdateRequest()
Calling this function multiple times will result in a single event
being delivered to the window.
Subclasses of QWindow should reimplement QWindow::event(), intercept
the event and call the application's rendering code, then call the
base class implementation.
*/
Subclasses of QWindow should reimplement event(), intercept the event and
call the application's rendering code, then call the base class
implementation.
\note The subclass' reimplementation of event() must invoke the base class
implementation, unless it is absolutely sure that the event does not need to
be handled by the base class. For example, the default implementation of
this function relies on QEvent::Timer events. Filtering them away would
therefore break the delivery of the update events.
*/
void QWindow::requestUpdate()
{
Q_D(QWindow);

View File

@ -292,11 +292,21 @@ bool QWidgetWindow::event(QEvent *event)
case QEvent::WindowBlocked:
qt_button_down = 0;
break;
case QEvent::UpdateRequest:
// This is not the same as an UpdateRequest for a QWidget. That just
// syncs the backing store while here we also must mark as dirty.
m_widget->repaint();
return true;
default:
break;
}
return m_widget->event(event) || QWindow::event(event);
if (m_widget->event(event) && event->type() != QEvent::Timer)
return true;
return QWindow::event(event);
}
QPointer<QWidget> qt_last_mouse_receiver = 0;

View File

@ -91,6 +91,7 @@ private slots:
void modalWindowModallity();
void modalWindowPosition();
void windowsTransientChildren();
void requestUpdate();
void initTestCase();
void cleanup();
@ -1666,6 +1667,25 @@ void tst_QWindow::windowsTransientChildren()
QVERIFY(isNativeWindowVisible(&child)); // Real children should be visible.
}
void tst_QWindow::requestUpdate()
{
QRect geometry(m_availableTopLeft + QPoint(80, 80), m_testWindowSize);
Window window;
window.setGeometry(geometry);
window.show();
QCoreApplication::processEvents();
QTRY_VERIFY(window.isExposed());
QVERIFY(window.received(QEvent::UpdateRequest) == 0);
window.requestUpdate();
QTRY_VERIFY(window.received(QEvent::UpdateRequest) == 1);
window.requestUpdate();
QTRY_VERIFY(window.received(QEvent::UpdateRequest) == 2);
}
#include <tst_qwindow.moc>
QTEST_MAIN(tst_QWindow)

View File

@ -55,6 +55,7 @@ private slots:
void reparentToAlreadyCreated();
void reparentToNotYetCreated();
void asViewport();
void requestUpdate();
};
void tst_QOpenGLWidget::create()
@ -305,6 +306,29 @@ void tst_QOpenGLWidget::asViewport()
QVERIFY(view->paintCount() == 0);
}
class PaintCountWidget : public QOpenGLWidget
{
public:
PaintCountWidget() : m_count(0) { }
void reset() { m_count = 0; }
void paintGL() Q_DECL_OVERRIDE { ++m_count; }
int m_count;
};
void tst_QOpenGLWidget::requestUpdate()
{
PaintCountWidget w;
w.resize(640, 480);
w.show();
QTest::qWaitForWindowExposed(&w);
w.reset();
QCOMPARE(w.m_count, 0);
w.windowHandle()->requestUpdate();
QTRY_VERIFY(w.m_count > 0);
}
QTEST_MAIN(tst_QOpenGLWidget)
#include "tst_qopenglwidget.moc"