Reputation: 43
How can I use a main file in macOS Swift and have an AppDelegate launch my own custom window? I am not talking about a custom NSWindow, but a counterpart to NSWindow.
Currently, in my app design, I am facing UI design constraints, and I am not satisfied with Apple's NSWindow design. I also have no room to customize it as I want. The only viable option that I think, with a small chance of working, is to try to achieve the NSWindow functionality at some necessary levels. Of course, I won't be able to implement all the functionality that comes with the standard NSWindow out of the box, but it's worth trying to push the boundaries of what's possible to satisfy some UI design needs.
The way I think about NSWindow is that it's like an NSView with added borders, a title, and window buttons for close, minimize, and full screen. Of course, it also has robust app delegate and system functionality, but what we see on screen is just a wrapper or shell that contains the content inside a window. I can do this myself in SwiftUI, as shown in the image. I'm not sharing the code because it's irrelevant to solving the issue, but this photo demonstrates the base and important part of a NSWindow as a wrapper.
Since my main goal is to bypass Apple’s rigid UI of NSWindow, I need to wrap my content in the same way I would in a window. However, since I am omitting and avoiding NSWindow to have a free canvas to build whatever I want. I've set my goal to simply draw a red rectangle with a given size on the screen. This would be the first and biggest step toward creating a standalone window.
Since I am building my own window, I believe I should use NSView or CGImage (CoreGraphics) to draw this red rectangle on the screen. In my opinion, using NSView would be a much easier approach since key press, mouse events, and animation functionality already exist in NSView. I see NSWindow as a kind of customized NSView that wraps its own NSView content and presents it to the screen. I need your help to solve this issue.
import Cocoa
import CoreGraphics
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
drawRedRectangle()
}
private func drawRedRectangle() {
let mainDisplayID = CGMainDisplayID()
let displayBounds = CGDisplayBounds(mainDisplayID)
guard let context = CGContext(
data: nil,
width: Int(displayBounds.width),
height: Int(displayBounds.height),
bitsPerComponent: 8,
bytesPerRow: 0,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue
) else {
print("Failed to create graphics context")
return
}
context.setFillColor(NSColor.red.cgColor)
let rect = CGRect(
x: (displayBounds.width - 400) / 2,
y: (displayBounds.height - 300) / 2,
width: 400,
height: 300
)
context.fill(rect)
guard let image = context.makeImage() else {
print("Failed to create image from context")
return
}
let displayContext = CGDisplayGetDrawingContext(mainDisplayID)
displayContext?.draw(image, in: displayBounds)
}
}
I am using a main.swift file to run the app on macOS 12.7.6 with Xcode 14.2 and a minimum deployment target of 12.0.
Upvotes: 0
Views: 81