How to loop through all Mac desktop spaces
OS X Desktop Picture Global Updating Across Spaces
In desktoppicture.db
an update
query can be run on the data
table with the path of the new image (value
). It shouldn't be necessary to delete
and then insert
the values, or use loops. Using an unscoped query calls update, and by doing so it will update every row in the data
table.
(The example below uses the SQLite.swift language layer, which uses a type-safe pure Swift interface)
func globalDesktopPicture(image: String) {
let paths: [String] = NSSearchPathForDirectoriesInDomains(.ApplicationSupportDirectory,
.UserDomainMask, true)
let appSup: String = paths.first!
let dbPath: String = (appSup as NSString).stringByAppendingPathComponent("Dock/desktoppicture.db")
let dbase = try? Connection("\(dbPath)")
let value = Expression<String?>("value")
let table = Table("data")
try! dbase!.run(table.update(value <- image))
system("/usr/bin/killall Dock")
}
The same concept/principle of updating the db applies just the same if you instead decide to use the traditional/legacy (bridging headers) method of doing SQLite3 queries:
func legacyGlobalDesktopPicture(image: String) {
let paths: [String] = NSSearchPathForDirectoriesInDomains(.ApplicationSupportDirectory,
.UserDomainMask, true)
let appSup: String = paths.first!
let dbPath: String = (appSup as NSString).stringByAppendingPathComponent("Dock/desktoppicture.db")
var db: COpaquePointer = nil
if sqlite3_open(dbPath, &db) == SQLITE_OK {
if sqlite3_exec(db, "UPDATE DATA SET VALUE = ('\(image)');", nil, nil, nil) != SQLITE_OK {
let errmsg = String.fromCString(sqlite3_errmsg(db))
print("error inserting table row: \(errmsg)")
}
system("/usr/bin/killall Dock")
}
sqlite3_close(db)
}
NOTE: The examples above are quite minimal and should include some error checking, etc.
Additional Info:
- How to get the path to the current space wallpaper?
- SQLite.swift Documentation : Updating Rows
- SQLite.swift / A type-safe, Swift-language layer over SQLite3
Seamlessly change all desktop spaces' wallpaper on Mac without killall Dock
I figured it out.
I am looping through all available screens and setting the wallpaper using setDesktopImageURL:forScreen:options:error::
for screen in NSScreen.screens {
try! NSWorkspace.shared.setDesktopImageURL(url, for: screen, options: [:])
}
This changes the wallpapers seamlessly, without the need for killall Dock
on all the screens but only if the desktop is the active space.
To make sure the wallpaper is changed when I am on another space (usually a fullscreen app), I added an observer for NSWorkspace.activeSpaceDidChangeNotification
on the NSWorkspace.shared.notificationCenter
which sets the desktop images again (using the code above). So whenever I go back to the desktop, this notification is invoked and the wallpaper is seamlessly updated.
I even went one step further and added the same observer also for the NSWorkspace.didWakeNotification
which updates the wallpaper as soon as the device wakes up which is cool!
How to assign application to all desktops (spaces) of Mac OS X Lion using Objective C?
You can use method setCollectionBehavior:
of NSWindow
with the NSWindowCollectionBehaviorCanJoinAllSpaces
bitwise flag.
It will make the window visible on all spaces.
NSUInteger collectionBehavior;
// Gets the current collection behavior of the window
collectionBehavior = [ myWindow collectionBehavior ];
// Adds the option to make the window visible on all spaces
collectionBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces;
// Sets the new collection behaviour
[ myWindow setCollectionBehavior: collectionBehavior ];
Note
This method was introduced in Mac OS X 10.6.
On Mac OS X 10.5, you'll need to use the canBeVisibleOnAllSpaces:
method of NSWindow
.
Desktop spaces are moving by their own
Go to System Preferencies
> Mission Control
Here check and (if enabled) disable Automatically rearrange Spaces
Related Topics
Changing Tab Bar Font in Swift
Difference Between Switch Cases "@Unknown Default" and "Default" in Swift 5
Combining Two Conditions in Nspredicate
Swift Check Type Against a Generic Type
Swiftui - Using Geometryreader Without Modifying the View Size
Swift 4.2+ Seeding a Random Number Generator
How to Set Title of Navigation Bar in Swift
Scene Kit Performance with Cube Test
Swift: How Can String.Join() Work Custom Types
Catch Objective-C Exception in Swift
Local Swift Packages Stopped Working in Xcode 13
Truncatingremainder VS Remainder in Swift
Xcode Autocomplete Does Not Work in Sources Folder of Swift Playgrounds