Skip to content

Commit 9c71bdb

Browse files
authored
Update UIKitDisplayList and AppKitDisplayList (#787)
1 parent 4190f6c commit 9c71bdb

File tree

11 files changed

+404
-116
lines changed

11 files changed

+404
-116
lines changed

Sources/COpenSwiftUI/Shims/AppKit/AppKit_Private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ typedef OPENSWIFTUI_ENUM(NSInteger, NSViewVibrantBlendingStyle) {
3434

3535
@interface NSView ()
3636
@property (getter=isOpaque) BOOL opaque;
37+
@property (nonatomic) BOOL ignoreHitTest;
38+
- (nullable NSResponder *)_nextResponderForEvent:(nullable NSEvent *)event;
3739
- (void)_updateLayerGeometryFromView;
3840
- (void)_updateLayerShadowFromView;
3941
- (void)_updateLayerShadowColorFromView;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// AllowsWindowActivationEventsResponder.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for 6.5.4
6+
// Status: WIP
7+
// ID: 302179F1EB9AE99B83C6A183C0B4143E (?)
8+
9+
#if os(macOS)
10+
// TODO
11+
class AllowsWindowActivationEventsResponder {}
12+
13+
// MARK: - AllowsWindowActivationEventsKey
14+
15+
private struct AllowsWindowActivationEventsKey: EnvironmentKey {
16+
static var defaultValue: Bool?
17+
}
18+
19+
extension EnvironmentValues {
20+
var allowsWindowActivationEvents: Bool? {
21+
get { self[AllowsWindowActivationEventsKey.self] }
22+
set { self[AllowsWindowActivationEventsKey.self] = newValue }
23+
}
24+
}
25+
#endif

Sources/OpenSwiftUI/Render/DisplayList/AppKitDisplayList.swift

Lines changed: 150 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,25 @@
22
// AppKitDisplayList.swift
33
// OpenSwiftUI
44
//
5-
// Audited for 6.0.87
6-
// Status: WIP
5+
// Audited for 6.5.4
6+
// Status: Complete
77
// ID: 33EEAA67E0460DA84AE814EA027152BA (SwiftUI)
88

99
#if os(macOS)
10-
@_spi(DisplayList_ViewSystem) import OpenSwiftUICore
10+
@_spi(ForOpenSwiftUIOnly)
11+
@_spi(DisplayList_ViewSystem)
12+
import OpenSwiftUICore
1113
import AppKit
1214
import OpenSwiftUISymbolDualTestsSupport
1315
import COpenSwiftUI
1416
import QuartzCore_Private
17+
import OpenRenderBoxShims
1518
import OpenSwiftUI_SPI
1619

17-
// MARK: - NSViewPlatformViewDefinition [TODO]
20+
// MARK: - NSViewPlatformViewDefinition
1821

1922
final class NSViewPlatformViewDefinition: PlatformViewDefinition, @unchecked Sendable {
20-
override final class var system: PlatformViewDefinition.System { .nsView }
23+
override static var system: PlatformViewDefinition.System { .nsView }
2124

2225
override static func makeView(kind: PlatformViewDefinition.ViewKind) -> AnyObject {
2326
let view: NSView
@@ -27,47 +30,25 @@ final class NSViewPlatformViewDefinition: PlatformViewDefinition, @unchecked Sen
2730
case .projection:
2831
view = _NSProjectionView()
2932
case .mask:
30-
view = _NSGraphicsView()
31-
view.mask = _NSInheritedView()
32-
initView(view.mask!, kind: kind)
33+
view = _NSInheritedView()
34+
let maskView = _NSInheritedView()
35+
view.mask = maskView
36+
initView(maskView, kind: .inherited)
3337
default:
3438
view = kind.isContainer ? _NSInheritedView() : _NSGraphicsView()
3539
}
3640
initView(view, kind: kind)
3741
return view
3842
}
39-
40-
private static func initView(_ view: NSView, kind: PlatformViewDefinition.ViewKind) {
41-
view.wantsLayer = true
42-
43-
if kind != .platformView && kind != .platformGroup {
44-
view.setFlipped(true)
45-
view.autoresizesSubviews = false
46-
// TODO - UnifiedHitTestingFeature.isEnabled
47-
// setIgnoreHitTest: true
48-
}
49-
50-
switch kind {
51-
case .color, .image, .shape:
52-
view.layer?.edgeAntialiasingMask = [.layerTopEdge, .layerBottomEdge, .layerLeftEdge, .layerRightEdge]
53-
view.layer?.allowsEdgeAntialiasing = true
54-
break
55-
case .geometry, .projection, .mask:
56-
view.layer?.allowsGroupOpacity = false
57-
view.layer?.allowsGroupBlending = false
58-
default:
59-
break
60-
}
61-
}
6243

63-
// Audited for 6.5.4
6444
override static func makeLayerView(type: CALayer.Type, kind: PlatformViewDefinition.ViewKind) -> AnyObject {
6545
let cls: NSView.Type
66-
if kind == .shape {
46+
switch kind {
47+
case .shape:
6748
cls = _NSShapeHitTestingView.self
68-
} else if kind == .platformLayer {
49+
case .platformLayer:
6950
cls = _NSPlatformLayerView.self
70-
} else {
51+
default:
7152
cls = kind.isContainer ? _NSInheritedView.self : _NSGraphicsView.self
7253
}
7354
let view = cls.init()
@@ -78,37 +59,97 @@ final class NSViewPlatformViewDefinition: PlatformViewDefinition, @unchecked Sen
7859
return view
7960
}
8061

81-
override class func makePlatformView(view: AnyObject, kind: PlatformViewDefinition.ViewKind) {
62+
override static func makePlatformView(view: AnyObject, kind: PlatformViewDefinition.ViewKind) {
8263
Self.initView(view as! NSView, kind: kind)
8364
}
8465

66+
override static func makeDrawingView(options: PlatformDrawableOptions) -> any PlatformDrawable {
67+
let view: NSView & PlatformDrawable
68+
if options.isAccelerated && ORBDevice.isSupported() {
69+
view = RBDrawingView(options: options)
70+
} else {
71+
view = CGDrawingView(options: options)
72+
}
73+
view.layerContentsRedrawPolicy = .onSetNeedsDisplay
74+
view.layerContentsPlacement = .topLeft
75+
initView(view, kind: .drawing)
76+
return view
77+
}
78+
8579
override static func setPath(_ path: Path, shapeView: AnyObject) {
86-
let view = unsafeBitCast(shapeView, to: _NSShapeHitTestingView.self)
80+
guard let view = shapeView as? _NSShapeHitTestingView else { return }
8781
view.path = path
8882
}
8983

90-
override class func setProjectionTransform(_ transform: ProjectionTransform, projectionView: AnyObject) {
84+
override static func setProjectionTransform(_ transform: ProjectionTransform, projectionView: AnyObject) {
9185
guard let view = projectionView as? _NSProjectionView else {
9286
return
9387
}
9488
view.projectionTransform = transform
95-
view.layer?.transform = .init(transform)
89+
view.layer?.transform = CATransform3D(transform)
90+
}
91+
92+
override static func getRBLayer(drawingView: AnyObject) -> AnyObject? {
93+
guard let rbView = drawingView as? RBDrawingView else { return nil }
94+
return rbView.layer
95+
}
96+
97+
override static func setIgnoresEvents(_ state: Bool, of view: AnyObject) {
98+
guard !ResponderBasedHitTesting.enabled else { return }
99+
if UnifiedHitTestingFeature.isEnabled {
100+
if let customizing = view as? RecursiveIgnoreHitTestCustomizing {
101+
customizing.recursiveIgnoreHitTest = state
102+
}
103+
} else {
104+
let view = unsafeBitCast(view, to: NSView.self)
105+
view.ignoreHitTest = state
106+
}
107+
}
108+
109+
override static func setAllowsWindowActivationEvents(_ value: Bool?, for view: AnyObject) {
110+
guard !ResponderBasedHitTesting.enabled else { return }
111+
if let customizing = view as? AcceptsFirstMouseCustomizing {
112+
customizing.customAcceptsFirstMouse = value
113+
}
96114
}
97115

98-
override class func setAllowsWindowActivationEvents(_ value: Bool?, for view: AnyObject) {
99-
_openSwiftUIUnimplementedWarning()
116+
override static func setHitTestsAsOpaque(_ value: Bool, for view: AnyObject) {
117+
guard !ResponderBasedHitTesting.enabled else { return }
118+
if let customizing = view as? HitTestsAsOpaqueCustomizing {
119+
customizing.hitTestsAsOpaque = value
120+
}
100121
}
101122

102-
override class func setHitTestsAsOpaque(_ value: Bool, for view: AnyObject) {
103-
_openSwiftUIUnimplementedWarning()
123+
private static func initView(_ view: NSView, kind: PlatformViewDefinition.ViewKind) {
124+
view.wantsLayer = true
125+
if kind != .platformView && kind != .platformGroup {
126+
view.setFlipped(true)
127+
view.autoresizesSubviews = false
128+
view.clipsToBounds = false
129+
if !UnifiedHitTestingFeature.isEnabled {
130+
view.ignoreHitTest = true
131+
}
132+
}
133+
switch kind {
134+
case .color, .image, .shape:
135+
let layer = view.layer!
136+
layer.edgeAntialiasingMask = [.layerTopEdge, .layerBottomEdge, .layerLeftEdge, .layerRightEdge]
137+
layer.allowsEdgeAntialiasing = true
138+
case .inherited, .geometry, .projection, .mask:
139+
let layer = view.layer!
140+
layer.allowsGroupOpacity = false
141+
layer.allowsGroupBlending = false
142+
default:
143+
break
144+
}
104145
}
105146
}
106147

107148
// MARK: - _NSGraphicsView
108149

109150
typealias PlatformGraphicsView = _NSGraphicsView
110151

111-
class _NSGraphicsView: NSView {
152+
class _NSGraphicsView: NSView, RecursiveIgnoreHitTestCustomizing, AcceptsFirstMouseCustomizing {
112153
var recursiveIgnoreHitTest: Bool = false
113154

114155
var customAcceptsFirstMouse: Bool?
@@ -120,13 +161,43 @@ class _NSGraphicsView: NSView {
120161
required init?(coder: NSCoder) {
121162
super.init(coder: coder)
122163
}
164+
165+
override func hitTest(_ point: NSPoint) -> NSView? {
166+
guard !ResponderBasedHitTesting.enabled else {
167+
return super.hitTest(point)
168+
}
169+
if UnifiedHitTestingFeature.isEnabled {
170+
guard !recursiveIgnoreHitTest,
171+
alphaValue >= ViewResponder.minOpacityForHitTest else {
172+
return nil
173+
}
174+
return super.hitTest(point)
175+
} else {
176+
guard !ignoreHitTest, frame.contains(point) else {
177+
return nil
178+
}
179+
return self
180+
}
181+
}
182+
183+
override func _nextResponder(for event: NSEvent?) -> NSResponder? {
184+
nextResponder
185+
}
186+
187+
override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
188+
guard !ResponderBasedHitTesting.enabled,
189+
let value = effectiveAcceptsFirstMouse else {
190+
return super.acceptsFirstMouse(for: event)
191+
}
192+
return value
193+
}
123194
}
124195

125196
// MARK: - _NSInheritedView
126197

127198
typealias PlatformInheritedView = _NSInheritedView
128199

129-
class _NSInheritedView: _NSGraphicsView {
200+
class _NSInheritedView: _NSGraphicsView, HitTestsAsOpaqueCustomizing {
130201
var hitTestsAsOpaque: Bool = false
131202

132203
override init(frame frameRect: NSRect) {
@@ -136,11 +207,30 @@ class _NSInheritedView: _NSGraphicsView {
136207
required init?(coder: NSCoder) {
137208
super.init(coder: coder)
138209
}
210+
211+
override func hitTest(_ point: NSPoint) -> NSView? {
212+
guard !ResponderBasedHitTesting.enabled,
213+
UnifiedHitTestingFeature.isEnabled else {
214+
return super.hitTest(point)
215+
}
216+
guard !isHiddenOrHasHiddenAncestor, !recursiveIgnoreHitTest else {
217+
return nil
218+
}
219+
for subview in subviews.reversed() {
220+
let convertedPoint = convert(point, from: superview)
221+
if let result = subview.hitTest(convertedPoint) {
222+
return result
223+
}
224+
}
225+
guard hitTestsAsOpaque, frame.contains(point) else {
226+
return nil
227+
}
228+
return self
229+
}
139230
}
140231

141-
// MARK: - _NSProjectionView [6.5.4]
232+
// MARK: - _NSProjectionView
142233

143-
@objc
144234
private class _NSProjectionView: _NSInheritedView {
145235
var projectionTransform: ProjectionTransform
146236

@@ -158,11 +248,11 @@ private class _NSProjectionView: _NSInheritedView {
158248

159249
override func _updateLayerGeometryFromView() {
160250
super._updateLayerGeometryFromView()
161-
layer?.transform = .init(projectionTransform)
251+
layer?.transform = CATransform3D(projectionTransform)
162252
}
163253
}
164254

165-
// MARK: - _NSShapeHitTestingView [WIP]
255+
// MARK: - _NSShapeHitTestingView
166256

167257
@objc
168258
private class _NSShapeHitTestingView: _NSGraphicsView {
@@ -179,15 +269,22 @@ private class _NSShapeHitTestingView: _NSGraphicsView {
179269
}
180270

181271
override func hitTest(_ point: NSPoint) -> NSView? {
182-
// path.contains(, eoFill: false)
183-
_openSwiftUIUnimplementedWarning()
184-
return nil
272+
guard !ResponderBasedHitTesting.enabled else {
273+
return super.hitTest(point)
274+
}
275+
if UnifiedHitTestingFeature.isEnabled, super.hitTest(point) == nil {
276+
return nil
277+
}
278+
let point = convert(point, from: superview)
279+
guard path.contains(point, eoFill: false) else {
280+
return nil
281+
}
282+
return self
185283
}
186284
}
187285

188286
// MARK: - _NSPlatformLayerView
189287

190-
@objc
191288
private class _NSPlatformLayerView: _NSGraphicsView {
192289
override init(frame frameRect: NSRect) {
193290
super.init(frame: frameRect)

0 commit comments

Comments
 (0)