EglFS: make sure resize events are delivered

Make sure that resize events are delivered when the platform
plugin overrides the geometry set in setGeometry().

This fixes a race condition where a widget was resized to its
sizeHint() while the window was maximized, and the content was
shown scaled on the screen.

The problem is that the widget gets the wrong size from
QWidget::setWindowState() (which calls adjustSize() in order to support
normalGeometry). This size is used to resize the backingStore. When the
QWindow is resized, it calls QEglFSWindow::setGeometry() which corrects the
size to screen()->availableGeometry(), and triggers a GeometryChangeEvent
since the size was corrected.

This ends up in QGuiApplicationPrivate::processGeometryChangeEvent() which
will not send a resize event, since the size has not changed (it is always
availableGeometry()). Therefore the widget is never resized, and the
backingStore remains the wrong size.

Task-number: QTBUG-34421
Change-Id: Iee49c53cc529de36010db2695d838d8c2284edd4
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
This commit is contained in:
Paul Olav Tvete 2013-11-06 12:43:51 +01:00 committed by The Qt Project
parent bc302359ca
commit d8f7a2ddf4
5 changed files with 22 additions and 16 deletions

View File

@ -1823,33 +1823,33 @@ void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePr
return;
QRect newRect = e->newGeometry;
QRect cr = window->d_func()->geometry;
QRect oldRect = e->oldGeometry.isNull() ? window->d_func()->geometry : e->oldGeometry;
bool isResize = cr.size() != newRect.size();
bool isMove = cr.topLeft() != newRect.topLeft();
bool isResize = oldRect.size() != newRect.size();
bool isMove = oldRect.topLeft() != newRect.topLeft();
window->d_func()->geometry = newRect;
if (isResize || window->d_func()->resizeEventPending) {
QResizeEvent e(newRect.size(), cr.size());
QResizeEvent e(newRect.size(), oldRect.size());
QGuiApplication::sendSpontaneousEvent(window, &e);
window->d_func()->resizeEventPending = false;
if (cr.width() != newRect.width())
if (oldRect.width() != newRect.width())
window->widthChanged(newRect.width());
if (cr.height() != newRect.height())
if (oldRect.height() != newRect.height())
window->heightChanged(newRect.height());
}
if (isMove) {
//### frame geometry
QMoveEvent e(newRect.topLeft(), cr.topLeft());
QMoveEvent e(newRect.topLeft(), oldRect.topLeft());
QGuiApplication::sendSpontaneousEvent(window, &e);
if (cr.x() != newRect.x())
if (oldRect.x() != newRect.x())
window->xChanged(newRect.x());
if (cr.y() != newRect.y())
if (oldRect.y() != newRect.y())
window->yChanged(newRect.y());
}
}

View File

@ -141,9 +141,12 @@ void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::handleGeometryChange(QWindow *tlw, const QRect &newRect)
/*!
If \a oldRect is null, Qt will use the previously reported geometry instead.
*/
void QWindowSystemInterface::handleGeometryChange(QWindow *tlw, const QRect &newRect, const QRect &oldRect)
{
QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect);
QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect, oldRect);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}

View File

@ -130,7 +130,7 @@ public:
static void handleTouchCancelEvent(QWindow *w, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier);
static void handleTouchCancelEvent(QWindow *w, ulong timestamp, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier);
static void handleGeometryChange(QWindow *w, const QRect &newRect);
static void handleGeometryChange(QWindow *w, const QRect &newRect, const QRect &oldRect = QRect());
static void handleCloseEvent(QWindow *w, bool *accepted = 0);
static void handleEnterEvent(QWindow *w, const QPointF &local = QPointF(), const QPointF& global = QPointF());
static void handleLeaveEvent(QWindow *w);

View File

@ -117,11 +117,12 @@ public:
class GeometryChangeEvent : public WindowSystemEvent {
public:
GeometryChangeEvent(QWindow *tlw, const QRect &newGeometry)
: WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry)
GeometryChangeEvent(QWindow *tlw, const QRect &newGeometry, const QRect &oldGeometry)
: WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry), oldGeometry(oldGeometry)
{ }
QPointer<QWindow> tlw;
QRect newGeometry;
QRect oldGeometry;
};
class EnterEvent : public WindowSystemEvent {

View File

@ -210,15 +210,17 @@ void QEglFSWindow::setVisible(bool visible)
void QEglFSWindow::setGeometry(const QRect &r)
{
QRect rect;
if (m_flags.testFlag(HasNativeWindow))
bool forceFullscreen = m_flags.testFlag(HasNativeWindow);
if (forceFullscreen)
rect = screen()->availableGeometry();
else
rect = r;
QPlatformWindow::setGeometry(rect);
// if we corrected the size, trigger a resize event
if (rect != r)
QWindowSystemInterface::handleGeometryChange(window(), rect);
QWindowSystemInterface::handleGeometryChange(window(), rect, r);
}
QRect QEglFSWindow::geometry() const