Cycle to next desktop picture?


I wonder if someone could help. I’m fairly new to Applescript and have been trying to do this for a little while, but I haven’t succeeded yet.

I have my desktop background image set to use a pictures folder and change picture randomly every 30 minutes. What I’d like to be able to write is an applescript that will allow me to make the desktop picture cycle to the next one.

To explain better, here’s an example of how I’d use it:
I’m using my computer, and my desktop background changes, as it does every 30 minutes.
However, I decide I’m not in the mood for the picture it’s chosen.
I run my applescript, and it replaces the picture with the next random picture instead.
If I don’t like that one, I can run the script again to pick yet another different one.
30 minutes later, my desktop picture changes again as usual.

Does anybody have any ideas how to achieve this?

Any help would be greatly appreciated.

The more basic question is how would you do that if you weren’t using an AppleScript?

Wouldn’t it be better if you simply selected from a folder of images and made them the desktop? Here’s how you set a desktop picture:

tell application "Finder" to set desktop picture to file "YourPic.jpg" of desktop

To get a picture at random from a folder somewhere (where you would fill in the path to the folder rather than choosing it every time:

tell application "Finder"
set pfiles to files of (choose folder) as alias list
set desktop picture to some item of pfiles
end tell

This will error, of course, if the chosen folder doesn’t contain suitable desktop pics

Edit - took out the word “file”

Or better than the previous post - this script:

-- saved as stay-open application

to setPic()
	tell application "Finder"
		set pfiles to files of (choose folder) as alias list -- replace choose folder with the path to a folder with valid desktop pics in it.
		set desktop picture to some item of pfiles -- some chooses at random
	end tell
end setPic

on run
	my setPic() -- a new pic when you start the program
end run

on idle
	my setPic()
	return 30 * 60 -- in seconds is 30 minutes. -- a new pic every 30 minutes while the program is running
end idle

on quit
	set btn to button returned of (display dialog "Do you want to quit or choose a new picture?" buttons {"Quit", "New Picture"} default button "New Picture")
	if btn = "Quit" then
		continue quit
		my setPic()
	end if
end quit

-- So to get a new pic you quit the application, get this dialog and continue with a new pic, or quit.

I suppose you could try something like this, James:

tell application "System Events" to tell property list item "ChangeTime" of ¬
	property list item 1 of property list item "Background" of property list file ¬
	((path to preferences as Unicode text) & "")
	set v to value
	set value to (v div 0.5) - v + 0.01
end tell


Fantastic, thankyou - that’s precisely what I was after!

Could you possibly explain part of it to me though, please?

I understand the first section that refers to the ChangeTime item in the desktop plist (which, for me is normally 1800), and I understand what that value is.

But what does

set v to value
set value to (v div 0.5) - v + 0.01

Actually do to it?

Thanks again

James Frost

Doesn’t work on mm, Kai. Returns “System Events got an error: NSReceiverEvaluationScriptError: 4”. When I look at the plist file, it does have a “Background” and a “ChangeTime”, but it errors on “value”. [in 10.4.6]

What’s mm?

It works for me, but not every time I run it - seems to be sort of every other time.

I don’t know if it makes any difference, but for me Background has three… ‘sub-keys’, if you like. I’m not sure what the proper term is - they’re 1952288145, 69667456 and default. I think they all seem to have the same contents, though.

Any ideas why it doesn’t work every time? And please could someone explain the bit of code that I mentioned earlier?


Sorry for the initials - mm is my machine.

I don’t know why Kai chose that construction instead of v as integer + .01, because I don’t know what “value” is - my machine won’t compile Kai’s script.

It’s just an abbreviation for “my machine”. You may also occasionally see OMM: “on my machine”.

This might work a little better, since it attempts to change the value of all relevant keys. (I’m hoping that this version will work for Adam, too):

tell application "System Events" to tell (property list item "ChangeTime" of (property list items where ¬
	name of property list items contains "ChangeTime")) of property list item "Background" of ¬
	property list file ((path to preferences as Unicode text) & "") to if exists then
	set v to item 1 of (get value)
	set value to (v div 0.5) - v + 0.01
end if

I was getting around to that, James, but my other work has a habit of intervening - and explanations can sometimes take longer to formulate than solutions. :wink:

My first thought was to try changing the value of the “ChangeTime” property list item to a very small value (to trigger a change of the current desktop picture) - and then change it back again immediately (to restore the original delay). Fine in theory but, each time the script was run, this caused the desktop picture to be changed twice.

I then tried setting the value to to the existing default, but that had no effect whatsoever. The current desktop picture simply stayed put. So clearly, to invoke a change of picture, the new value must be a different one. It then occurred to me that one way forward might be to make a tiny adjustment to the value. One small enough not to make a difference to the general delay, but enough to register as a change - thus causing the desktop picture to be replaced. However, since even small changes can have a cumulative effect, the ideal algorithm should make a small adjustment in one direction - and then, on the next run, reverse the direction of the change.

I’m not sure how familiar you are with the ‘div’ operator but, since it performs integral division, it’s a handy (and fast) way of rounding a number down to the nearest integer. So the expression ‘v div 0.5’ multiplies v by 2 and then rounds it down to an integer. Subtracting v from that then produces a result that is equivalent to v’s integer part - v’s fractional part. (If v has no fractional part, there’s essentially no change.) The final operation (+ 0.01) simply adds one hundredth of a second to the result.

The complete calculation has the effect of alternately adding or subtracting one hundredth of a second to/from the value. So if the current value has no fractional part:

set v to 1800
set r to v div 0.5
--> 3600
set r to r - v
--> 1800
set r to r + 0.01
--> 1800.01

And if it contains a fractional element:

set v to 1800.01
set r to v div 0.5
--> 3600
set r to r - v
--> 1799.99
set r to r + 0.01
--> 1800.0

This might demonstrate the effect better:

set v to 1800 (* or any other positive integer *)
	display dialog v
	set v to (v div 0.5) - v + 0.01
end repeat

Now I’m confused, Adam. Is the problem that the script won’t compile - or that it results in an error “NSReceiverEvaluationScriptError: 4” when run?

Sorry, Kai - sloppiness. The original comment is correct. Compiles but won’t run.

And it does, too with the proviso that I wait a small portion of a second before clicking again. Even works with solid colors (which I prefer),

Yes, when changing a picture, there’s a delay involved (which occurs even when using System Preferences). Using the script, I can usually fire off a couple of quick changes that are implemented, but not much beyond that. In any case, the aim here is to view a desktop image and then change it if desired - while preserving the default sequence and timing. I wouldn’t use this approach for much more than that. Thanks for the confirmation that it now works on your machine.

Thanks so much for this script, Kai - it works perfectly now, and does precisely what I wanted it to! I’d’ve never worked that out on my own! So I’ve learnt something, too - which is always a good thing.

Thanks again,


Thanks for the feedback, James (always appreciated - good or bad). Delighted to hear it worked out for you. :slight_smile:

If i use this

tell application “Finder” to set desktop picture to file “YourPic.jpg” of desktop

Desktop picture dont change, but if i turn “change picture: every 5 minutes” off in Desktop & Screen Saver, then it works.

How to turn that on/off using AppleScript, preferrably without UI Scripting?

Try this, cirno:

tell application "System Events" to set value of property list item "Change" of (property list items ¬
	where name of property list items contains "Change") of property list item "Background" of ¬
	property list file ((path to preferences as Unicode text) & "") to "Never"
tell application "Finder" to set desktop picture to file "YourPic.jpg"

A question from a while ago, but I kinda took a few pointers from here and there across the web, posting my rendition of this one.

tell application "System Events"
	tell current desktop
		set change interval to (change interval div 0.5) - change interval + 0.1
	end tell
end tell