summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Sørvig <msorvig@trolltech.com>2009-07-30 12:19:50 (GMT)
committerMorten Sørvig <msorvig@trolltech.com>2009-07-30 12:19:50 (GMT)
commit26e9f4e077c49d1191835def595e4fb70ee50be2 (patch)
treeb2aae6fa449b5ec99c60e2483f84f176d26d4257
parentd09fa4a816c6b9ccf306b7e1a887c4a4b1dc2f4e (diff)
downloadQt-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.mm7
-rw-r--r--src/gui/painting/qregion.h1
-rw-r--r--src/gui/painting/qregion_mac.cpp38
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)