Hello Greg @DTS Engineer ,
Thank you for your prompt response.
I've implemented your suggestion and tried several approaches to solve my window management issue, but I'm still encountering problems that I'd like to clarify.
Current Issue:
When clicking on a country flag in the Earth window, multiple instances of both the main window and Earth window are being created, despite using the same window IDs.
What I've Tried:
I've implemented a window management system with a centralized WindowManager singleton that queues window open/close operations and prevents operations that are too frequent:
// WindowManager singleton to manage window operations
class WindowManager {
static let shared = WindowManager()
// Serial queue to ensure window operations happen in order
private let windowOperationQueue = DispatchQueue(label: "com.mxsing.travelimmersive.windowqueue")
// Track last operation time by window ID
private var lastOperationTime: [String: Date] = [:]
// Track pending open requests
private var pendingOpenRequests: [String: Bool] = [:]
private init() {}
// Request to open a window
func requestOpenWindow(id: String, openWindowAction: @escaping (String) -> Void, updateStateAction: @escaping () -> Void) {
windowOperationQueue.async { [weak self] in
guard let self = self else { return }
// Check for pending requests
if self.pendingOpenRequests[id] == true {
print("Window Manager: Already have pending request for \(id), ignoring")
return
}
// Check last operation time to prevent frequent operations
let now = Date()
if let lastTime = self.lastOperationTime[id],
now.timeIntervalSince(lastTime) < 1.0 {
print("Window Manager: Operation for \(id) too frequent, ignoring")
return
}
// Update timestamp and request status
self.lastOperationTime[id] = now
self.pendingOpenRequests[id] = true
// Execute UI operations on main thread
DispatchQueue.main.async {
print("Window Manager: Opening window \(id)")
updateStateAction() // Update state first
openWindowAction(id) // Then open window
// Clear pending status after 300ms
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.pendingOpenRequests[id] = false
}
}
}
}
}
In AppModel, I've added methods to safely open and close windows:
// Safe window opening method that uses the WindowManager
func safeOpenWindow(id: String, openWindowAction: @escaping (String) -> Void) {
WindowManager.shared.requestOpenWindow(
id: id,
openWindowAction: openWindowAction,
updateStateAction: { [weak self] in
// Update state
if id == "MainWindow" {
self?.mainWindowOpen = true
self?.updateWindowExistence(id: id, exists: true)
} else if id == "Earth" {
self?.isGlobeWindowOpen = true
self?.updateWindowExistence(id: id, exists: true)
}
}
)
}
// Safe window opening method that uses the WindowManager
func safeOpenWindow(id: String, openWindowAction: @escaping (String) -> Void) {
WindowManager.shared.requestOpenWindow(
id: id,
openWindowAction: openWindowAction,
updateStateAction: { [weak self] in
// Update state
if id == "MainWindow" {
self?.mainWindowOpen = true
self?.updateWindowExistence(id: id, exists: true)
} else if id == "Earth" {
self?.isGlobeWindowOpen = true
self?.updateWindowExistence(id: id, exists: true)
}
}
)
}
When a flag is clicked in the Earth view, we call this method:
// In CountryButtonView
Button {
// Process country selection
appModel.handleGlobeFlagTap(country: country.name)
// Use safe window manager to open main window
print("Flag clicked: Opening main window through safe window manager")
appModel.safeOpenWindow(id: "MainWindow") { windowId in
openWindow(id: windowId)
}
} label: {
// Button content
}
Key Questions:
Window Closure Detection: Is it possible to directly capture the event when a user manually closes a window in visionOS? If so, how can we detect this event?
Duplicate Windows: According to the documentation, calling openWindow(id:) should focus an existing window with the same ID rather than creating a new one. However, in our testing, we still see multiple instances of windows with the same ID being created. How can we prevent duplicate windows from being created?
Is there a recommended way to implement reliable window state tracking in visionOS that avoids these issues? Are there any undocumented limitations or best practices we should be aware of?
I've included the relevant code snippets above, but I'm happy to provide more implementation details if needed. Any guidance would be greatly appreciated.
Thank you
Topic:
Spatial Computing
SubTopic:
General
Tags: