From 10fb3e6d313329ebee2b85e501874cacb950de32 Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 20 Jun 2026 14:35:15 +0200 Subject: [PATCH 1/7] Fixed: scale accumulation in scaleUnitSquareToSize: when setting bounds size --- AppKit/CPView.j | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 31b26f017..e8ac8a4b4 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1474,6 +1474,21 @@ var CPViewHighDPIDrawingEnabled = YES; origin.y *= size.height / frameSize.height; } + [self willChangeValueForKey:@"scaleSize"]; + if (size.width === 0 || size.height === 0) + { + _scaleSize = CGSizeMake(1.0, 1.0); + } + else + { + _scaleSize = CGSizeMake(frameSize.width / size.width, frameSize.height / size.height); + } + _isScaled = (_scaleSize.width !== 1.0 || _scaleSize.height !== 1.0); + [self didChangeValueForKey:@"scaleSize"]; + + // Recompute hierarchy scale size for this view and its descendants + [self _scaleSizeUnitSquareToSize:CGSizeMake(1.0, 1.0)]; + if (_layer) [_layer _owningViewBoundsChanged]; From 5fd2f49266a56bb163dc2a7246d5d9f6acf7694b Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 20 Jun 2026 14:55:27 +0200 Subject: [PATCH 2/7] safety checks --- AppKit/CPView.j | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index e8ac8a4b4..f0689d0e9 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1475,18 +1475,16 @@ var CPViewHighDPIDrawingEnabled = YES; } [self willChangeValueForKey:@"scaleSize"]; - if (size.width === 0 || size.height === 0) - { - _scaleSize = CGSizeMake(1.0, 1.0); - } - else - { + + if (size && size.width !== 0 && size.height !== 0 && frameSize) _scaleSize = CGSizeMake(frameSize.width / size.width, frameSize.height / size.height); - } + else + _scaleSize = CGSizeMake(1.0, 1.0); + _isScaled = (_scaleSize.width !== 1.0 || _scaleSize.height !== 1.0); [self didChangeValueForKey:@"scaleSize"]; - // Recompute hierarchy scale size for this view and its descendants + // Recompute hierarchy scale size safely [self _scaleSizeUnitSquareToSize:CGSizeMake(1.0, 1.0)]; if (_layer) @@ -1502,7 +1500,6 @@ var CPViewHighDPIDrawingEnabled = YES; [self _updateTrackingAreasWithRecursion:YES]; } - /*! Notifies subviews that the superview changed size. @param aSize the size of the old superview From e6e676c91ee5e334de660d15e4ec582f2571af4f Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 20 Jun 2026 15:00:21 +0200 Subject: [PATCH 3/7] more safety checks --- AppKit/CPView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index f0689d0e9..289fc7f89 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -2618,7 +2618,7 @@ setBoundsOrigin: */ - (void)_scaleSizeUnitSquareToSize:(CGSize)aSize { - _hierarchyScaleSize = CGSizeMakeCopy([_superview _hierarchyScaleSize]); + _hierarchyScaleSize = _superview ? CGSizeMakeCopy([_superview _hierarchyScaleSize]) : CGSizeMake(1.0, 1.0); if (_isScaled) { From 344cbd0660b91202768fcbb7e48575d95c4096da Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 20 Jun 2026 15:01:35 +0200 Subject: [PATCH 4/7] formatting --- Tests/AppKit/CPTabViewTest.j | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/AppKit/CPTabViewTest.j b/Tests/AppKit/CPTabViewTest.j index fe149ab60..24802da29 100644 --- a/Tests/AppKit/CPTabViewTest.j +++ b/Tests/AppKit/CPTabViewTest.j @@ -69,6 +69,7 @@ { var tabs = [_tabView tabs]; [_tabView setBounds:CGRectMake(100, 100, 20, 300)]; + // Perform this manually for the sake of the unit test. [_tabView layoutIfNeeded]; [self assert:([tabs boundsSize].width / 2) equals:CGRectGetMidX([tabs bounds])]; From cff2fd8ed9e0245b998ae21f1e43c597c696a44b Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 20 Jun 2026 17:51:11 +0200 Subject: [PATCH 5/7] optimized version --- AppKit/CPView.j | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 289fc7f89..fb1bbc8d9 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1474,18 +1474,24 @@ var CPViewHighDPIDrawingEnabled = YES; origin.y *= size.height / frameSize.height; } - [self willChangeValueForKey:@"scaleSize"]; + var newScaleSize; if (size && size.width !== 0 && size.height !== 0 && frameSize) - _scaleSize = CGSizeMake(frameSize.width / size.width, frameSize.height / size.height); + newScaleSize = CGSizeMake(frameSize.width / size.width, frameSize.height / size.height); else - _scaleSize = CGSizeMake(1.0, 1.0); + newScaleSize = CGSizeMake(1.0, 1.0); - _isScaled = (_scaleSize.width !== 1.0 || _scaleSize.height !== 1.0); - [self didChangeValueForKey:@"scaleSize"]; + // Only update and propagate if the scale factor has actually changed + if (!CGSizeEqualToSize(_scaleSize, newScaleSize)) + { + [self willChangeValueForKey:@"scaleSize"]; + _scaleSize = newScaleSize; + _isScaled = (_scaleSize.width !== 1.0 || _scaleSize.height !== 1.0); + [self didChangeValueForKey:@"scaleSize"]; - // Recompute hierarchy scale size safely - [self _scaleSizeUnitSquareToSize:CGSizeMake(1.0, 1.0)]; + // Only traverse the view hierarchy if there is a genuine change in the scale state + [self _scaleSizeUnitSquareToSize:CGSizeMake(1.0, 1.0)]; + } if (_layer) [_layer _owningViewBoundsChanged]; From 301e940236245740030fb66e91772593fcdc8c9f Mon Sep 17 00:00:00 2001 From: daboe01 Date: Wed, 26 Aug 2026 20:56:38 +0200 Subject: [PATCH 6/7] formatting --- AppKit/CPView.j | 1 - 1 file changed, 1 deletion(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index fb1bbc8d9..29660594b 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1489,7 +1489,6 @@ var CPViewHighDPIDrawingEnabled = YES; _isScaled = (_scaleSize.width !== 1.0 || _scaleSize.height !== 1.0); [self didChangeValueForKey:@"scaleSize"]; - // Only traverse the view hierarchy if there is a genuine change in the scale state [self _scaleSizeUnitSquareToSize:CGSizeMake(1.0, 1.0)]; } From 67b4798caad37c7b8b598bb2cf8888a27868e1da Mon Sep 17 00:00:00 2001 From: daboe01 Date: Wed, 26 Aug 2026 20:57:53 +0200 Subject: [PATCH 7/7] formatting --- Tests/AppKit/CPTabViewTest.j | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/AppKit/CPTabViewTest.j b/Tests/AppKit/CPTabViewTest.j index 24802da29..fe149ab60 100644 --- a/Tests/AppKit/CPTabViewTest.j +++ b/Tests/AppKit/CPTabViewTest.j @@ -69,7 +69,6 @@ { var tabs = [_tabView tabs]; [_tabView setBounds:CGRectMake(100, 100, 20, 300)]; - // Perform this manually for the sake of the unit test. [_tabView layoutIfNeeded]; [self assert:([tabs boundsSize].width / 2) equals:CGRectGetMidX([tabs bounds])];