Skip to content

Commit 45a34bd

Browse files
committed
Merge remote-tracking branch 'origin/feat/sheet' into feat/sheet
2 parents 0d175e7 + dce5be6 commit 45a34bd

File tree

8 files changed

+62
-22
lines changed

8 files changed

+62
-22
lines changed

Sources/AppKitBackend/AppKitBackend.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,21 +1725,38 @@ public final class AppKitBackend: AppBackend {
17251725
return SIMD2(x: Int(size.width), y: Int(size.height))
17261726
}
17271727

1728-
public func showSheet(_ sheet: NSCustomSheet, window: NSCustomWindow) {
1728+
public func showSheet(_ sheet: NSCustomSheet, sheetParent: Any) {
17291729
// Critical sheets stack. beginSheet only shows a nested sheet
17301730
// after its parent gets dismissed.
1731+
let window = sheetParent as! NSCustomWindow
17311732
window.beginCriticalSheet(sheet)
1733+
window.managedAttachedSheet = sheet
17321734
}
17331735

1734-
public func dismissSheet(_ sheet: NSCustomSheet, window: NSCustomWindow) {
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+
17351745
window.endSheet(sheet)
17361746
}
17371747

17381748
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+
17391754
let backgroundView = NSView()
17401755
backgroundView.wantsLayer = true
17411756
backgroundView.layer?.backgroundColor = color.nsColor.cgColor
17421757

1758+
sheet.backgroundView = backgroundView
1759+
17431760
if let existingContentView = sheet.contentView {
17441761
let container = NSView()
17451762
container.translatesAutoresizingMaskIntoConstraints = false
@@ -1777,6 +1794,8 @@ public final class NSCustomSheet: NSCustomWindow, NSWindowDelegate {
17771794

17781795
public var interactiveDismissDisabled: Bool = false
17791796

1797+
public var backgroundView: NSView?
1798+
17801799
public func dismiss() {
17811800
onDismiss?()
17821801
self.contentViewController?.dismiss(self)
@@ -2209,6 +2228,8 @@ public class NSCustomWindow: NSWindow {
22092228
var customDelegate = Delegate()
22102229
var persistentUndoManager = UndoManager()
22112230

2231+
var managedAttachedSheet: NSCustomSheet?
2232+
22122233
/// Allows the backing scale factor to be overridden. Useful for keeping
22132234
/// UI tests consistent across devices.
22142235
///

Sources/Gtk/Widgets/Window.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import CGtk
77
open class Window: Widget {
88
public var child: Widget?
99

10+
public var managedAttachedSheet: Window?
11+
1012
public convenience init() {
1113
self.init(gtk_window_new())
1214
}

Sources/Gtk3Backend/Gtk3Backend.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,9 +1517,3 @@ struct Gtk3Error: LocalizedError {
15171517
"gerror: code=\(code), domain=\(domain), message=\(message)"
15181518
}
15191519
}
1520-
1521-
extension Gtk3.Window: SheetImplementation {
1522-
public var sheetSize: SIMD2<Int> {
1523-
SIMD2(x: size.width, y: size.height)
1524-
}
1525-
}

Sources/GtkBackend/GtkBackend.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,18 +1635,30 @@ public final class GtkBackend: AppBackend {
16351635
}
16361636
}
16371637

1638-
public func showSheet(_ sheet: Gtk.Window, window: ApplicationWindow) {
1638+
public func showSheet(_ sheet: Gtk.Window, sheetParent: Any) {
1639+
let window = sheetParent as! Gtk.Window
16391640
sheet.isModal = true
16401641
sheet.isDecorated = false
16411642
sheet.setTransient(for: window)
16421643
sheet.present()
1644+
window.managedAttachedSheet = sheet
16431645
}
16441646

1645-
public func dismissSheet(_ sheet: Gtk.Window, window: ApplicationWindow) {
1647+
public func dismissSheet(_ sheet: Gtk.Window, sheetParent: Any) {
1648+
let window = sheetParent as! Gtk.Window
1649+
1650+
if let nestedSheet = window.managedAttachedSheet {
1651+
dismissSheet(nestedSheet, sheetParent: sheet)
1652+
}
1653+
1654+
defer { window.managedAttachedSheet = nil }
1655+
16461656
let key: OpaquePointer = OpaquePointer(sheet.widgetPointer)
1657+
16471658
if let ctx = sheetContexts[key] {
16481659
ctx.isProgrammaticDismiss = true
16491660
}
1661+
16501662
sheet.destroy()
16511663
sheetContexts.removeValue(forKey: key)
16521664
connectedCloseHandlers.remove(key)

Sources/SwiftCrossUI/Backend/AppBackend.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -627,12 +627,12 @@ public protocol AppBackend: Sendable {
627627
/// app modal, a standalone window, or a modal for a window of its choosing.
628628
func showSheet(
629629
_ sheet: Sheet,
630-
window: Window
630+
sheetParent: Any
631631
)
632632

633633
/// Dismisses a sheet programmatically.
634634
/// Gets used by the ``View/sheet`` modifier to close a sheet.
635-
func dismissSheet(_ sheet: Sheet, window: Window)
635+
func dismissSheet(_ sheet: Sheet, sheetParent: Any)
636636

637637
/// Get the dimensions of a sheet
638638
func size(ofSheet sheet: Sheet) -> SIMD2<Int>
@@ -1281,12 +1281,12 @@ extension AppBackend {
12811281

12821282
public func showSheet(
12831283
_ sheet: Sheet,
1284-
window: Window
1284+
sheetParent: Any
12851285
) {
12861286
todo()
12871287
}
12881288

1289-
public func dismissSheet(_ sheet: Sheet, window: Window) {
1289+
public func dismissSheet(_ sheet: Sheet, sheetParent: Any) {
12901290
todo()
12911291
}
12921292

Sources/SwiftCrossUI/Environment/EnvironmentValues.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ public struct EnvironmentValues {
128128
/// The backend in use. Mustn't change throughout the app's lifecycle.
129129
let backend: any AppBackend
130130

131+
/// The backend's representation of the class that owns the current sheet,
132+
/// if any. This is a very internal detail that should never get
133+
/// exposed to users.
134+
package var sheetParent: Any?
135+
131136
/// Presents an 'Open file' dialog fit for selecting a single file. Some
132137
/// backends only allow selecting either files or directories but not both
133138
/// in a single dialog. Returns `nil` if the user cancels the operation.

Sources/SwiftCrossUI/Views/Modifiers/SheetModifier.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ struct SheetModifier<Content: View, SheetContent: View>: TypeSafeView {
8080
let dismissAction = DismissAction(action: { [isPresented] in
8181
isPresented.wrappedValue = false
8282
})
83-
let sheetEnvironment = environment.with(\.dismiss, dismissAction)
83+
84+
var sheetEnvironment =
85+
environment
86+
.with(\.dismiss, dismissAction)
87+
.with(\.sheetParent, sheet)
8488

8589
let result = children.sheetContentNode!.update(
8690
with: sheetContent(),
@@ -123,13 +127,13 @@ struct SheetModifier<Content: View, SheetContent: View>: TypeSafeView {
123127

124128
backend.showSheet(
125129
sheet,
126-
window: environment.window! as! Backend.Window
130+
sheetParent: (environment.sheetParent ?? environment.window)!
127131
)
128132
children.sheet = sheet
129133
} else if !isPresented.wrappedValue && children.sheet != nil {
130134
backend.dismissSheet(
131135
children.sheet as! Backend.Sheet,
132-
window: environment.window! as! Backend.Window
136+
sheetParent: (environment.sheetParent ?? environment.window)!
133137
)
134138
children.sheet = nil
135139
children.sheetContentNode = nil

Sources/UIKitBackend/UIKitBackend+Sheet.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,18 @@ extension UIKitBackend {
2222

2323
public func showSheet(
2424
_ sheet: CustomSheet,
25-
window: UIWindow
25+
sheetParent: Any
2626
) {
27-
var topController = window.rootViewController
28-
while let presented = topController?.presentedViewController {
29-
topController = presented
27+
var topController: UIViewController? = nil
28+
if let window = sheetParent as? UIWindow {
29+
topController = window.rootViewController
30+
} else {
31+
topController = sheetParent as? UIViewController
3032
}
3133
topController?.present(sheet, animated: true)
3234
}
3335

34-
public func dismissSheet(_ sheet: CustomSheet, window: UIWindow) {
36+
public func dismissSheet(_ sheet: CustomSheet, sheetParent: Any) {
3537
// If this sheet has a presented view controller (nested sheet), dismiss it first
3638
if let presentedVC = sheet.presentedViewController {
3739
presentedVC.dismiss(animated: false) { [weak sheet] in

0 commit comments

Comments
 (0)