Skip to content

Commit f8bfe27

Browse files
committed
Implement basics of WinUIBackend under new layout system (RNG ex works)
Coming along well so far. The biggest hiccups have been setting the minimum sizes of windows (not solved yet) and getting the 'natural size' of UI elements before they're rendered (kinda solved with a hacky workaround).
1 parent eea0ead commit f8bfe27

File tree

6 files changed

+804
-315
lines changed

6 files changed

+804
-315
lines changed

Examples/Sources/RandomNumberGeneratorExample/RandomNumberGeneratorApp.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,6 @@ struct RandomNumberGeneratorApp: App {
7575
}
7676
}
7777
.defaultSize(width: 500, height: 0)
78-
.windowResizability(.contentSize)
78+
.windowResizability(.contentMinSize)
7979
}
8080
}

Package.resolved

Lines changed: 184 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/SwiftCrossUI/App.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ extension App {
7474

7575
private static func extractSwiftBundlerMetadata() -> AppMetadata? {
7676
guard let executable = Bundle.main.executableURL else {
77-
print("No executable url")
77+
print("warning: No executable url")
7878
return nil
7979
}
8080

@@ -86,7 +86,6 @@ extension App {
8686
// Check if executable has Swift Bundler metadata magic bytes.
8787
let bytes = Array(data)
8888
guard bytes.suffix(8) == Array("SBUNMETA".utf8) else {
89-
print("no magic bytes")
9089
return nil
9190
}
9291

Sources/SwiftCrossUI/Backend/AppBackend.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public protocol AppBackend {
141141

142142
/// Runs an action in the app's main thread if required to perform UI updates
143143
/// by the backend. Predominantly used by ``Publisher`` to publish changes to a thread
144-
/// compatible with dispatching UI updates.
144+
/// compatible with dispatching UI updates. Can be synchronous or asynchronous (for now).
145145
func runInMainThread(action: @escaping () -> Void)
146146

147147
/// Computes the root environment for an app (e.g. by checking the system's current
@@ -384,7 +384,10 @@ public protocol AppBackend {
384384
/// - Parameter progressFraction: If `nil`, then the bar should show an indeterminate
385385
/// animation if possible.
386386
func updateProgressBar(
387-
_ widget: Widget, progressFraction: Double?, environment: EnvironmentValues)
387+
_ widget: Widget,
388+
progressFraction: Double?,
389+
environment: EnvironmentValues
390+
)
388391

389392
/// Creates a popover menu (the sort you often see when right clicking on
390393
/// apps). The menu won't be visible until you call
@@ -502,7 +505,7 @@ extension AppBackend {
502505
todo()
503506
}
504507

505-
public func setColor(ofColorableRectangle widget: Widget) {
508+
public func setColor(ofColorableRectangle widget: Widget, to color: Color) {
506509
todo()
507510
}
508511

@@ -696,7 +699,7 @@ extension AppBackend {
696699
public func createProgressBar() -> Widget {
697700
todo()
698701
}
699-
func updateProgressBar(
702+
public func updateProgressBar(
700703
_ widget: Widget,
701704
progressFraction: Double?,
702705
environment: EnvironmentValues
@@ -734,14 +737,14 @@ extension AppBackend {
734737
) {
735738
todo()
736739
}
737-
func showAlert(
740+
public func showAlert(
738741
_ alert: Alert,
739742
window: Window?,
740743
responseHandler handleResponse: @escaping (Int) -> Void
741744
) {
742745
todo()
743746
}
744-
func dismissAlert(_ alert: Alert, window: Window?) {
747+
public func dismissAlert(_ alert: Alert, window: Window?) {
745748
todo()
746749
}
747750

Sources/SwiftCrossUI/State/Publisher.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import CoreFoundation
21
import Dispatch
32
import Foundation
43

@@ -15,7 +14,7 @@ public class Publisher {
1514

1615
/// The time at which the last update merging event occurred in
1716
/// `observeOnMainThreadAvoidingStarvation`.
18-
private var lastUpdateMergeTime: CFAbsoluteTime = 0
17+
private var lastUpdateMergeTime: TimeInterval = 0
1918
/// The amount of time taken per state update, exponentially averaged over time.
2019
private var exponentiallySmoothedUpdateLength: Double = 0
2120

@@ -106,7 +105,7 @@ public class Publisher {
106105
// It's a bit of a hack but we just reuse the serial update handling queue
107106
// for synchronisation since updating this variable isn't super time sensitive
108107
// as long as it happens within the next update or two.
109-
let mergeTime = CFAbsoluteTimeGetCurrent()
108+
let mergeTime = ProcessInfo.processInfo.systemUptime
110109
serialUpdateHandlingQueue.async {
111110
self.lastUpdateMergeTime = mergeTime
112111
}
@@ -127,9 +126,9 @@ public class Publisher {
127126

128127
// Run the closure and while we're at it measure how long it takes
129128
// so that we can use it when throttling if updates start backing up.
130-
let start = CFAbsoluteTimeGetCurrent()
129+
let start = ProcessInfo.processInfo.systemUptime
131130
closure()
132-
let elapsed = CFAbsoluteTimeGetCurrent() - start
131+
let elapsed = ProcessInfo.processInfo.systemUptime - start
133132

134133
// I chose exponential smoothing because it's simple to compute, doesn't
135134
// require storing a window of previous values, and quickly converges to
@@ -139,7 +138,7 @@ public class Publisher {
139138
elapsed / 2 + self.exponentiallySmoothedUpdateLength / 2
140139
}
141140

142-
if CFAbsoluteTimeGetCurrent() - self.lastUpdateMergeTime < 1 {
141+
if ProcessInfo.processInfo.systemUptime - self.lastUpdateMergeTime < 1 {
143142
// The factor of 1.5 was determined empirically. This algorithm is
144143
// open for improvements since it's purely here to reduce the risk
145144
// of UI freezes.

0 commit comments

Comments
 (0)