Fix constantly growing window bug with devicePixelRatio

Rectangles need to be mapped differently depending on what they are
used for. Expose events need to cover the entire geometry, so they must
be rounded up, potentially increasing the size. If we use the same
conversion for window geometries, it is possible to end up with a
feedback loop if the window reacts to the new size.

Task-number: QTBUG-43743
Change-Id: I7881cc77bf2148fed2ae743c4226617a61197434
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Paul Olav Tvete 2015-01-12 10:14:44 +01:00
parent 4448576ae0
commit c1d08afd31

View File

@ -151,7 +151,7 @@ static inline QRect mapToNative(const QRect &qtRect, int dpr)
return QRect(qtRect.x() * dpr, qtRect.y() * dpr, qtRect.width() * dpr, qtRect.height() * dpr);
}
// When converting native rects to Qt rects: round top/left towards the origin and
// When mapping expose events to Qt rects: round top/left towards the origin and
// bottom/right away from the origin, making sure that we cover the whole widget
static inline QPoint dpr_floor(const QPoint &p, int dpr)
@ -164,11 +164,15 @@ static inline QPoint dpr_ceil(const QPoint &p, int dpr)
return QPoint((p.x() + dpr - 1) / dpr, (p.y() + dpr - 1) / dpr);
}
static inline QRect mapFromNative(const QRect &xRect, int dpr)
static inline QRect mapExposeFromNative(const QRect &xRect, int dpr)
{
return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr));
}
static inline QRect mapGeometryFromNative(const QRect &xRect, int dpr)
{
return QRect(xRect.topLeft() / dpr, xRect.bottomRight() / dpr);
}
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
static inline bool isTransient(const QWindow *w)
@ -1718,7 +1722,7 @@ public:
return false;
if (expose->count == 0)
m_pending = false;
*m_region |= mapFromNative(QRect(expose->x, expose->y, expose->width, expose->height), m_dpr);
*m_region |= mapExposeFromNative(QRect(expose->x, expose->y, expose->width, expose->height), m_dpr);
return true;
}
@ -1746,7 +1750,7 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
{
const int dpr = int(devicePixelRatio());
QRect x_rect(event->x, event->y, event->width, event->height);
QRect rect = mapFromNative(x_rect, dpr);
QRect rect = mapExposeFromNative(x_rect, dpr);
if (m_exposeRegion.isEmpty())
m_exposeRegion = rect;
@ -1866,7 +1870,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
const int dpr = devicePixelRatio();
const QRect nativeRect = QRect(pos, QSize(event->width, event->height));
const QRect rect = mapFromNative(nativeRect, dpr);
const QRect rect = mapGeometryFromNative(nativeRect, dpr);
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
@ -1877,7 +1881,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
int newDpr = devicePixelRatio();
if (newDpr != dpr) {
QRect newRect = mapFromNative(nativeRect, newDpr);
QRect newRect = mapGeometryFromNative(nativeRect, newDpr);
QPlatformWindow::setGeometry(newRect);
QWindowSystemInterface::handleGeometryChange(window(), newRect);
}