Wednesday, April 27, 2016

How to loop through all Mac desktop spaces

Leave a Comment

I'm trying to set a desktop background for all screens AND spaces (preexisting and new). However, I can't seem to find a way to set the background for all the existing spaces (and any new spaces created use the old background).

Here is what I have so far:

let sqlData = NSMutableArray() let paths = NSSearchPathForDirectoriesInDomains(.ApplicationSupportDirectory, .UserDomainMask, true) let appSupportDirectory = paths.first! as NSString let dbPath = appSupportDirectory.stringByAppendingPathComponent("Dock/desktoppicture.db") as NSString  var db: COpaquePointer = nil if sqlite3_open(dbPath.UTF8String, &db) == SQLITE_OK {     var statement: COpaquePointer = nil      if sqlite3_exec(db, "DELETE FROM data", nil, nil, nil) != SQLITE_OK {         let errmsg = String.fromCString(sqlite3_errmsg(db))         print("error deleting table row: \(errmsg)")     }      if sqlite3_exec(db, "INSERT INTO DATA (VALUE) VALUES ('\(getBackgroundImagePath())');", nil, nil, nil) != SQLITE_OK {         let errmsg = String.fromCString(sqlite3_errmsg(db))         print("error inserting table row: \(errmsg)")     }      let workspace = NSWorkspace.sharedWorkspace()      for screen in NSScreen.screens()! {         do {             let options = workspace.desktopImageOptionsForScreen(screen)             try workspace.setDesktopImageURL(NSURL(fileURLWithPath: getBackgroundImagePath()), forScreen: screen, options: options!)         } catch let error as NSError {             NSLog("\(error.localizedDescription)")         }     }      system("/usr/bin/killall Dock") }  sqlite3_close(db) 

Note: I update the .db file found in ~/Library/Application Support/Dock/desktoppicture.db. Since this doesn't actually update the background, I then proceed to loop through each screen and set them manually.

Although this changes all of the screen's backgrounds, any non-active spaces are not changed, and any new spaces created use the old background.

I'm using this code within a small app I made on GitHub, and this is an issue a user reported. You can find the issue here (with a terminal solution).

Apple has a seemingly relevant project here, but even they don't update multiple spaces.

Also, if you update the background through the default mac settings app, it also doesn't change pre-existing spaces. Is it impossible?

1 Answers

Answers 1

OS X Desktop Picture Global Updating Across Spaces

(It's not impossible, however, definitely possible even without using loops.)

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.

func globalDesktopPicture {      let paths: [String] = NSSearchPathForDirectoriesInDomains(.ApplicationSupportDirectory,                                                               .UserDomainMask, true)     let appSup: String = paths.first!     let dbPath: String = (appSup as NSString).stringByAppendingPathComponent("Dock/desktoppicture.db")      let image : String = "/path/to/new/image"     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") } 

Keep in mind that this example is quite minimal and should include some error checking, etc. I'll leave those details up to you though, since this is really about showing how to update the desktop picture across all spaces. You might find some of the other information below helpful as well.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment