@@ -1697,25 +1697,59 @@ public final class AppKitBackend: AppBackend {
16971697 contentRect: NSRect (
16981698 x: 0 ,
16991699 y: 0 ,
1700- width: 400 , // Default width
1701- height: 400 // Default height
1700+ width: 400 ,
1701+ height: 400
17021702 ) ,
17031703 styleMask: [ . titled, . closable] ,
17041704 backing: . buffered,
17051705 defer: true
17061706 )
1707- sheet. contentView = content
1707+
1708+ let backgroundView = NSView ( )
1709+ backgroundView. translatesAutoresizingMaskIntoConstraints = false
1710+ backgroundView. wantsLayer = true
1711+
1712+ let contentView = NSView ( )
1713+ contentView. addSubview ( backgroundView)
1714+ contentView. addSubview ( content)
1715+ NSLayoutConstraint . activate ( [
1716+ contentView. topAnchor. constraint ( equalTo: content. topAnchor) ,
1717+ contentView. leadingAnchor. constraint ( equalTo: content. leadingAnchor) ,
1718+ contentView. bottomAnchor. constraint ( equalTo: content. bottomAnchor) ,
1719+ contentView. trailingAnchor. constraint ( equalTo: content. trailingAnchor) ,
1720+ contentView. topAnchor. constraint ( equalTo: backgroundView. topAnchor) ,
1721+ contentView. leadingAnchor. constraint ( equalTo: backgroundView. leadingAnchor) ,
1722+ contentView. bottomAnchor. constraint ( equalTo: backgroundView. bottomAnchor) ,
1723+ contentView. trailingAnchor. constraint ( equalTo: backgroundView. trailingAnchor) ,
1724+ ] )
1725+ contentView. translatesAutoresizingMaskIntoConstraints = false
1726+
1727+ sheet. contentView = contentView
1728+ sheet. backgroundView = backgroundView
17081729
17091730 return sheet
17101731 }
17111732
17121733 public func updateSheet(
17131734 _ sheet: NSCustomSheet ,
17141735 size: SIMD2 < Int > ,
1715- onDismiss: @escaping ( ) -> Void
1736+ onDismiss: @escaping ( ) -> Void ,
1737+ cornerRadius: Double ? ,
1738+ detents: [ PresentationDetent ] ,
1739+ dragIndicatorVisibility: Visibility ,
1740+ backgroundColor: Color ? ,
1741+ interactiveDismissDisabled: Bool
17161742 ) {
1717- sheet. contentView ? . frame . size = . init ( width: size. x, height: size. y)
1743+ sheet. setContentSize ( NSSize ( width: size. x, height: size. y) )
17181744 sheet. onDismiss = onDismiss
1745+
1746+ let background = sheet. backgroundView!
1747+ background. layer? . backgroundColor = backgroundColor? . nsColor. cgColor
1748+ sheet. interactiveDismissDisabled = interactiveDismissDisabled
1749+
1750+ // - dragIndicatorVisibility is only for mobile so we ignore it
1751+ // - detents are only for mobile so we ignore them
1752+ // - cornerRadius isn't supported by macOS so we ignore it
17191753 }
17201754
17211755 public func size( ofSheet sheet: NSCustomSheet ) -> SIMD2 < Int > {
@@ -1725,67 +1759,32 @@ public final class AppKitBackend: AppBackend {
17251759 return SIMD2 ( x: Int ( size. width) , y: Int ( size. height) )
17261760 }
17271761
1728- public func showSheet( _ sheet: NSCustomSheet , sheetParent: Any ) {
1729- // Critical sheets stack. beginSheet only shows a nested sheet
1730- // after its parent gets dismissed.
1731- let window = sheetParent as! NSCustomWindow
1732- window. beginSheet ( sheet)
1733- window. managedAttachedSheet = sheet
1734- }
1735-
1736- public func dismissSheet( _ sheet: NSCustomSheet , sheetParent: Any ) {
1737- let window = sheetParent as! NSCustomWindow
1738-
1739- if let nestedSheet = sheet. managedAttachedSheet {
1740- dismissSheet ( nestedSheet, sheetParent: sheet)
1741- }
1742-
1743- defer { window. managedAttachedSheet = nil }
1744-
1745- window. endSheet ( sheet)
1762+ public func presentSheet( _ sheet: NSCustomSheet , window: Window , parentSheet: Sheet ? ) {
1763+ let parent = parentSheet ?? window
1764+ // beginSheet and beginCriticalSheet should be equivalent here, because we
1765+ // directly present the sheet on top of the top-most sheet. If we were to
1766+ // instead present sheets on top of the root window every time, then
1767+ // beginCriticalSheet would produce the desired behaviour and beginSheet
1768+ // would wait for the parent sheet to finish before presenting the nested sheet.
1769+ parent. beginSheet ( sheet)
1770+ parent. nestedSheet = sheet
17461771 }
17471772
1748- public func setPresentationBackground( of sheet: NSCustomSheet , to color: Color ) {
1749- if let backgroundView = sheet. backgroundView {
1750- backgroundView. layer? . backgroundColor = color. nsColor. cgColor
1751- return
1752- }
1753-
1754- let backgroundView = NSView ( )
1755- backgroundView. wantsLayer = true
1756- backgroundView. layer? . backgroundColor = color. nsColor. cgColor
1757-
1758- sheet. backgroundView = backgroundView
1773+ public func dismissSheet( _ sheet: NSCustomSheet , window: Window , parentSheet: Sheet ? ) {
1774+ let parent = parentSheet ?? window
17591775
1760- if let existingContentView = sheet. contentView {
1761- let container = NSView ( )
1762- container. translatesAutoresizingMaskIntoConstraints = false
1763-
1764- container. addSubview ( backgroundView)
1765- backgroundView. translatesAutoresizingMaskIntoConstraints = false
1766- backgroundView. leadingAnchor. constraint ( equalTo: container. leadingAnchor) . isActive =
1767- true
1768- backgroundView. topAnchor. constraint ( equalTo: container. topAnchor) . isActive = true
1769- backgroundView. trailingAnchor. constraint ( equalTo: container. trailingAnchor) . isActive =
1770- true
1771- backgroundView. bottomAnchor. constraint ( equalTo: container. bottomAnchor) . isActive = true
1772-
1773- container. addSubview ( existingContentView)
1774- existingContentView. translatesAutoresizingMaskIntoConstraints = false
1775- existingContentView. leadingAnchor. constraint ( equalTo: container. leadingAnchor)
1776- . isActive = true
1777- existingContentView. topAnchor. constraint ( equalTo: container. topAnchor) . isActive = true
1778- existingContentView. trailingAnchor. constraint ( equalTo: container. trailingAnchor)
1779- . isActive = true
1780- existingContentView. bottomAnchor. constraint ( equalTo: container. bottomAnchor) . isActive =
1781- true
1782-
1783- sheet. contentView = container
1776+ // Dismiss nested sheets first
1777+ if let nestedSheet = sheet. nestedSheet {
1778+ dismissSheet ( nestedSheet, window: window, parentSheet: sheet)
1779+ // Although the current sheet has been dismissed programmatically,
1780+ // the nested sheets kind of haven't (at least, they weren't
1781+ // directly dismissed by SwiftCrossUI, so we must called onDismiss
1782+ // to let SwiftUI react to the dismissals of nested sheets).
1783+ nestedSheet. onDismiss ? ( )
17841784 }
1785- }
17861785
1787- public func setInteractiveDismissDisabled ( for sheet : NSCustomSheet , to disabled : Bool ) {
1788- sheet . interactiveDismissDisabled = disabled
1786+ parent . endSheet ( sheet )
1787+ parent . nestedSheet = nil
17891788 }
17901789}
17911790
@@ -1796,14 +1795,10 @@ public final class NSCustomSheet: NSCustomWindow, NSWindowDelegate {
17961795
17971796 public var backgroundView : NSView ?
17981797
1799- public func dismiss( ) {
1800- onDismiss ? ( )
1801- self . contentViewController? . dismiss ( self )
1802- }
1803-
18041798 @objc override public func cancelOperation( _ sender: Any ? ) {
18051799 if !interactiveDismissDisabled {
1806- dismiss ( )
1800+ sheetParent? . endSheet ( self )
1801+ onDismiss ? ( )
18071802 }
18081803 }
18091804}
@@ -2228,7 +2223,10 @@ public class NSCustomWindow: NSWindow {
22282223 var customDelegate = Delegate ( )
22292224 var persistentUndoManager = UndoManager ( )
22302225
2231- var managedAttachedSheet : NSCustomSheet ?
2226+ /// A reference to the sheet currently presented on top of this window, if any.
2227+ /// If the sheet itself has another sheet presented on top of it, then that doubly
2228+ /// nested sheet gets stored as the sheet's nestedSheet, and so on.
2229+ var nestedSheet : NSCustomSheet ?
22322230
22332231 /// Allows the backing scale factor to be overridden. Useful for keeping
22342232 /// UI tests consistent across devices.
0 commit comments