diff options
author | Morten Sørvig <msorvig@trolltech.com> | 2009-07-30 12:19:50 (GMT) |
---|---|---|
committer | Morten Sørvig <msorvig@trolltech.com> | 2009-07-30 12:19:50 (GMT) |
commit | 26e9f4e077c49d1191835def595e4fb70ee50be2 (patch) | |
tree | b2aae6fa449b5ec99c60e2483f84f176d26d4257 | |
parent | d09fa4a816c6b9ccf306b7e1a887c4a4b1dc2f4e (diff) | |
download | Qt-26e9f4e077c49d1191835def595e4fb70ee50be2.zip Qt-26e9f4e077c49d1191835def595e4fb70ee50be2.tar.gz Qt-26e9f4e077c49d1191835def595e4fb70ee50be2.tar.bz2 |
Mac/Carbon: Fix issue causing update(QRegion) to fail on large widgets.
HIViewSetNeedsDisplayInRegion fails on large regions with large
coordinates, fall back on updating the entire region in this case.
The task mentions coordinates outside the range of signed short, but
the provided example demonstrates failures in the 10-20K range as well.
-rw-r--r-- | src/gui/kernel/qwidget_mac.mm | 7 | ||||
-rw-r--r-- | src/gui/painting/qregion.h | 1 | ||||
-rw-r--r-- | src/gui/painting/qregion_mac.cpp | 38 |
3 files changed, 45 insertions, 1 deletions
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 70eea3a..3bbf5d4 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -3100,7 +3100,12 @@ void QWidgetPrivate::update_sys(const QRegion &rgn) return; dirtyOnWidget += rgn; #ifndef QT_MAC_USE_COCOA - HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgn.toQDRgn()), true); + RgnHandle rgnHandle = rgn.toQDRgnForUpdate_sys(); + if (rgnHandle) + HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgnHandle), true); + else { + HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow. + } #else // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect. const QRect &boundingRect = rgn.boundingRect(); diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index bfedcb1..6dfdc83 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -148,6 +148,7 @@ public: #elif defined(Q_WS_MAC) #if defined Q_WS_MAC32 RgnHandle toQDRgn() const; + RgnHandle toQDRgnForUpdate_sys() const; static QRegion fromQDRgn(RgnHandle shape); #endif #ifdef QT_MAC_USE_COCOA diff --git a/src/gui/painting/qregion_mac.cpp b/src/gui/painting/qregion_mac.cpp index b57f234..9b0e99f 100644 --- a/src/gui/painting/qregion_mac.cpp +++ b/src/gui/painting/qregion_mac.cpp @@ -155,6 +155,44 @@ RgnHandle QRegion::toQDRgn() const } return rgnHandle; } + +/*! + \internal + Create's a RegionHandle, it's the caller's responsibility to release. + Returns 0 if the QRegion overflows. +*/ +RgnHandle QRegion::toQDRgnForUpdate_sys() const +{ + RgnHandle rgnHandle = qt_mac_get_rgn(); + if(d->qt_rgn && d->qt_rgn->numRects) { + RgnHandle tmp_rgn = qt_mac_get_rgn(); + int n = d->qt_rgn->numRects; + const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData(); + while (n--) { + + // detect overflow. Tested for use with HIViewSetNeedsDisplayInRegion + // in QWidgetPrivate::update_sys(). + enum { HIViewSetNeedsDisplayInRegionOverflow = 10000 }; // empirically determined conservative value + qDebug() << qt_r->x() << qt_r->y() << qt_r->right() << qt_r->bottom(); + if (qt_r->right() > HIViewSetNeedsDisplayInRegionOverflow || qt_r->bottom() > HIViewSetNeedsDisplayInRegionOverflow) { + qt_mac_dispose_rgn(tmp_rgn); + qt_mac_dispose_rgn(rgnHandle); + return 0; + } + + SetRectRgn(tmp_rgn, + qMax(SHRT_MIN, qt_r->x()), + qMax(SHRT_MIN, qt_r->y()), + qMin(SHRT_MAX, qt_r->right() + 1), + qMin(SHRT_MAX, qt_r->bottom() + 1)); + UnionRgn(rgnHandle, tmp_rgn, rgnHandle); + ++qt_r; + } + qt_mac_dispose_rgn(tmp_rgn); + } + return rgnHandle; +} + #endif #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) |