├── Makefile ├── README.md ├── minimal ├── minimal.swift ├── minimal_large ├── minimal_large.swift └── pics ├── minimal_first_run.jpg └── minimal_smol.jpg /Makefile: -------------------------------------------------------------------------------- 1 | start: 2 | swiftc minimal.swift -o minimal -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## A Minimal Swift Window Script 2 | 3 | --- 4 | 5 | | _A tiny script that makes a window on MacOS :)_ | 6 | | ---- | 7 | ![Minimal window script with no title, just a small gray square window in the bottom left corner of the screen](./pics/minimal_smol.jpg) 8 | --- 9 | 10 | ## How to run 11 | 12 | ``` bash 13 | # --- to run: ---- 14 | ./minimal # for the spartan version 15 | ./minimal_large # for the nice version 16 | # --- to compile: ---- 17 | make 18 | # it's just wrapping `swiftc minimal.swift -o minimal` 19 | ``` 20 | 21 | ## Backstory 22 | 23 | Heavily inspired by [little-fbdev-critcl-play](https://github.com/osnr/little-fbdev-critcl-play) I was curious to know if you can draw pixels directly to the MacOS "framebuffer" (short answer: no, there's no `/dev/fb0` on MacOS, long answer: maybe you can make a file that auto-writes to Quartz Display Services or something??? That's for another time though.) Frustrated with all of that I went down a different rabbit hole: can I, in a small script, make a MacOS window? Without Xcode, without Tk, or SDL ... 24 | 25 | I stumbled on [this great StackOverflow question](https://stackoverflow.com/questions/30763229/display-window-on-osx-using-swift-without-xcode-or-nib) & got the bones of `minimal.swift`. 26 | 27 | So I copy/pasted that answer into a Swift file on my latop, ran the compile command & got a 28 | bunch of errors. 29 | 30 | As that StackOverflow question is from 2015, the answer from 2017 (Swift 3), and I'm now writing in 2023 (using Swift 5.7), some 31 | things have broken. [This comment gets us most of the way there:](https://stackoverflow.com/questions/30763229/display-window-on-osx-using-swift-without-xcode-or-nib#comment105128857_46348417) 32 | > I am running Swift 5 and I had to change a couple of things, but it works. 33 | 34 | The changes: 35 | | **Swift 3** | **Swift 4** | 36 | | ------------|-------------| 37 | | `NSApplication.shared()` | `NSApplication.shared` | 38 | | `NSApplicationActivationPolicy` | `NSApplication.ActivationPolicy` | 39 | | `NSTitledWindowMask` | `.titled` | 40 | 41 | But I ran into one more thing ... 42 | 43 | ``` bash 44 | minimal.swift:18:31: error: 'NSBackingStoreType' has been renamed to 'NSWindow.BackingStoreType' 45 | styleMask:.titled,backing:NSBackingStoreType.buffered,defer:false) 46 | ^~~~~~~~~~~~~~~~~~ 47 | NSWindow.BackingStoreType 48 | AppKit.NSBackingStoreType:2:18: note: 'NSBackingStoreType' was obsoleted in Swift 4 49 | public typealias NSBackingStoreType = NSWindow.BackingStoreType 50 | ^ 51 | make: *** [Makefile:2: start] Error 1 52 | ``` 53 | 54 | Okay, so we change `NSBackingStoreType` to `NSWindow` & ... 55 | 56 | ![A little square, gray window titled minimal with an app title of minimal in the top left](./pics/minimal_first_run.jpg) 57 | 58 | _**it works!**_ 59 | 60 | This made me think ... is this _**the most minimal**_? How 61 | much of this can we remove? Turns out, most of it! Granted, we are throwing away 62 | the ability to `[⌘ + Q]` quit & the app title, but those are just niceties lol 63 | 64 | ``` swift 65 | // The smolest Swift script to make a window in Swift 5.7.2: 66 | import Cocoa 67 | let nsapp = NSApplication.shared 68 | NSApp.setActivationPolicy(NSApplication.ActivationPolicy.regular) 69 | let window = NSWindow.init(contentRect:NSMakeRect(0, 0, 200, 200), styleMask:.titled,backing:NSWindow.BackingStoreType.buffered,defer:false) 70 | window.makeKeyAndOrderFront(nil) 71 | NSApp.activate(ignoringOtherApps:true) 72 | NSApp.run() 73 | ``` 74 | 75 | ![Minimal window script with no title, just a small gray square window in the bottom left corner of the screen](./pics/minimal_smol.jpg) -------------------------------------------------------------------------------- /minimal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwervo/minimal-macos-window/5023658fe383a79f2a8b3f3491f4552c213830d4/minimal -------------------------------------------------------------------------------- /minimal.swift: -------------------------------------------------------------------------------- 1 | // From: https://stackoverflow.com/questions/30763229/display-window-on-osx-using-swift-without-xcode-or-nib 2 | import Cocoa 3 | 4 | let nsapp = NSApplication.shared 5 | NSApp.setActivationPolicy(NSApplication.ActivationPolicy.regular) 6 | 7 | /* 8 | // It seems like this compiles in minimal_og but doesn't actually create a menu? 9 | let menubar = NSMenu() 10 | let appMenuItem = NSMenuItem() 11 | menubar.addItem(appMenuItem) 12 | NSApp.mainMenu = menubar 13 | 14 | let appMenu = NSMenu() 15 | // This is clever, but since we're removing the two places it's used below, can remove! 16 | let appName = ProcessInfo.processInfo.processName 17 | 18 | // Can remove this, enables quit via [⌘ + Q] 19 | let quitMenuItem = NSMenuItem.init(title:"Quit " + appName, action:#selector(NSApplication.terminate),keyEquivalent:"q") 20 | appMenu.addItem(quitMenuItem); 21 | appMenuItem.submenu = appMenu; 22 | */ 23 | 24 | let window = NSWindow.init( contentRect:NSMakeRect(0, 0, 200, 200), styleMask:.titled, backing:NSWindow.BackingStoreType.buffered, defer:false) 25 | // Can remove this, but the window is going to be at the bottom left 26 | // window.cascadeTopLeft(from:NSMakePoint(20, 20)) 27 | 28 | // Don't need window titles ¯\_(ツ)_/¯ 29 | // window.title = appName; 30 | 31 | // Without this the window never appears 32 | window.makeKeyAndOrderFront(nil) 33 | // Okay, I could remove this, but having an app create a window but 34 | // be in the background doesn't feel right. 35 | NSApp.activate(ignoringOtherApps:true) 36 | 37 | NSApp.run() -------------------------------------------------------------------------------- /minimal_large: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwervo/minimal-macos-window/5023658fe383a79f2a8b3f3491f4552c213830d4/minimal_large -------------------------------------------------------------------------------- /minimal_large.swift: -------------------------------------------------------------------------------- 1 | // From: https://stackoverflow.com/questions/30763229/display-window-on-osx-using-swift-without-xcode-or-nib 2 | import Cocoa 3 | 4 | let nsapp = NSApplication.shared 5 | NSApp.setActivationPolicy(NSApplication.ActivationPolicy.regular) 6 | let menubar = NSMenu() 7 | let appMenuItem = NSMenuItem() 8 | menubar.addItem(appMenuItem) 9 | NSApp.mainMenu = menubar 10 | let appMenu = NSMenu() 11 | let appName = ProcessInfo.processInfo.processName 12 | let quitTitle = "Quit " + appName 13 | let quitMenuItem = NSMenuItem.init(title:quitTitle, 14 | action:#selector(NSApplication.terminate),keyEquivalent:"q") 15 | appMenu.addItem(quitMenuItem); 16 | appMenuItem.submenu = appMenu; 17 | let window = NSWindow.init(contentRect:NSMakeRect(0, 0, 200, 200), 18 | styleMask:.titled,backing:NSWindow.BackingStoreType.buffered,defer:false) 19 | window.cascadeTopLeft(from:NSMakePoint(20,20)) 20 | window.title = appName; 21 | window.makeKeyAndOrderFront(nil) 22 | NSApp.activate(ignoringOtherApps:true) 23 | NSApp.run() -------------------------------------------------------------------------------- /pics/minimal_first_run.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwervo/minimal-macos-window/5023658fe383a79f2a8b3f3491f4552c213830d4/pics/minimal_first_run.jpg -------------------------------------------------------------------------------- /pics/minimal_smol.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwervo/minimal-macos-window/5023658fe383a79f2a8b3f3491f4552c213830d4/pics/minimal_smol.jpg --------------------------------------------------------------------------------