QMacStyle: Fix scroller memory leak

Calling initWithFrame repeatedly on the same object
leaks memory since internal structures allocated on
the previous init call will not be released.

However, initWithFrame is the only API that can set
scroller direction, which is does based on the geometry.

Use two scroller objets, one for each of the horizontal
and vertical cases.

Task-number: QTBUG-60004
Change-Id: I5d07b62e6969a1824ab705941ac4d0340139b99c
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
This commit is contained in:
Morten Johan Sørvig 2017-04-10 11:17:51 +02:00 committed by Gabriel de Dietrich
parent 5cde07350c
commit b113107419
2 changed files with 14 additions and 5 deletions

View File

@ -2110,7 +2110,12 @@ QMacStyle::QMacStyle()
name:NSPreferredScrollerStyleDidChangeNotification name:NSPreferredScrollerStyleDidChangeNotification
object:nil]; object:nil];
d->nsscroller = [[NSScroller alloc] init]; // Create scroller objects. Scroller internal direction setup happens
// on initWithFrame and cannot be changed later on. Create two scrollers
// initialized with fake geometry. Correct geometry is set at draw time.
d->horizontalScroller = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)];
d->verticalScroller = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)];
d->indicatorBranchButtonCell = nil; d->indicatorBranchButtonCell = nil;
} }
@ -2119,7 +2124,8 @@ QMacStyle::~QMacStyle()
Q_D(QMacStyle); Q_D(QMacStyle);
QMacAutoReleasePool pool; QMacAutoReleasePool pool;
[reinterpret_cast<NSScroller*>(d->nsscroller) release]; [d->horizontalScroller release];
[d->verticalScroller release];
NotificationReceiver *receiver = static_cast<NotificationReceiver *>(d->receiver); NotificationReceiver *receiver = static_cast<NotificationReceiver *>(d->receiver);
[[NSNotificationCenter defaultCenter] removeObserver:receiver]; [[NSNotificationCenter defaultCenter] removeObserver:receiver];
@ -5451,8 +5457,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
[NSGraphicsContext setCurrentContext:[NSGraphicsContext [NSGraphicsContext setCurrentContext:[NSGraphicsContext
graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]];
NSScroller *scroller = reinterpret_cast<NSScroller*>(d->nsscroller); NSScroller *scroller = isHorizontal ? d->horizontalScroller : d-> verticalScroller;
[scroller initWithFrame:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())];
// mac os behaviour: as soon as one color channel is >= 128, // mac os behaviour: as soon as one color channel is >= 128,
// the bg is considered bright, scroller is dark // the bg is considered bright, scroller is dark
const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget);

View File

@ -115,6 +115,9 @@
// We mean it. // We mean it.
// //
Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
Q_FORWARD_DECLARE_OBJC_CLASS(NSScroller);
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/* /*
@ -246,7 +249,8 @@ public:
CFAbsoluteTime defaultButtonStart; CFAbsoluteTime defaultButtonStart;
bool mouseDown; bool mouseDown;
void* receiver; void* receiver;
void *nsscroller; NSScroller *horizontalScroller;
NSScroller *verticalScroller;
void *indicatorBranchButtonCell; void *indicatorBranchButtonCell;
NSView *backingStoreNSView; NSView *backingStoreNSView;
QHash<QCocoaWidget, NSView *> cocoaControls; QHash<QCocoaWidget, NSView *> cocoaControls;