Windows-like Minimize toggle on Dock icons

The script aims to replicate a Windows-like behavior for clicking on dock icons in macOS.
When one (1) app Window:

  1. When an app is open but minimized, clicking its dock icon will unminimize and bring the app window to the front (native in both macOS and Windows).
  2. When an app is open, frontmost and not minimized, clicking its dock icon will minimize the app window (native only in Windows).
  3. When an app is open but not frontmost, clicking it's dock icon will bring the latest app window to front (native in both macOS and Windows).
  4. When an app is not open, clicking its dock icon will launch the app (native in both macOS and Windows).

When more than one (1) app Window:

  1. For apps with multiple windows open, clicking the dock icon bring last window to the front.

This behavior is not native to macOS. By default on Mac, clicking a dock icon of a minimized app does not unminimize it, it's unhidden. The script aims to make the dock behavior more similar to the Windows taskbar, where a single click toggles the window state with the Minimize action.

Presets can be found here BetterTouchTool Preset Sharing Platform

Props to yw4z's Enhanced Dock for macOS for inspiration.

2024-10-03 at 09.38.07

Hey! Was looking for something like that for quite some time. But I see, you just recently created this script, so got lucky.... Two things, where it is not working is - when you have multiple windows open for same app. When clicking icon it is not minimizing window.... As well as not un-minimizing app at all, have to right click to get it to work. And other one - weirdly if, lets say, you close all app windows by X and app is still open (when having dot under app icon on dock), script is not opening app at all. When you click icon, it does nothing. So have to quit app for good and open again. Wonder if it is something fixable.... Anyways, Thanks for the script! :slight_smile:
P.S When importing the script, why it has two duplicate entries @ BTT? Have to disable/delete one in order to avoid getting mini menu to choose which script to run when doing left click ...

Hi Andreas, thanks for implementing this as it is very handy.
I can't get it to work however. I will admit, I am not a BTT pro but I do have another existing preset that is working.
When I import your preset I get a warning about a duplicate preset and then it imports it.
Everything seems to be set up but I don't see the expected behaviour when clicking on any Dock icon twice.
Some help would be really appreciated, thanks.

Screen Shot 2024-11-15 at 17.15.44 pm

I have the same problem.

Same issue here

the preset does import 2 copies so easy solution-just delete one! works great for me on m setup. Just find the 2 trackpad gestures, i. use 1 finger tap for mine and delete 1-should be right next to each other and both have same color tag when hovered wlll expand to say Preset-Windows Like Minimize....

Doesn't work on BTT 5.155 even if remove duplicated gestures. Please fix!

good preset though I think it has a few kinks and fixing them make it function much better. Here is a screenshot of my updated action

Works much better. This I have setup to 1 finger tap and works like a charm, The fix is simply just delete a couple things 1)the duplicate action included in preset 2) the END.IF and IF functions which are not needed and make it more complicated.. No need for second IF function because, 1st IF function states, application is not the active window or ELSE it is! Binary option. Therefore no need for another IF because our function already tells BTT that if App is not active, then open hovered app in dock ELSE minimize app

Hope that helps and thanks for original preset

Hello wynstaxxx, mind to share please? For some reason the preset isnt working for me.

yah sure i also have a version that i use know that hides instead of mminiizes…..with te expection of some apps that dont like to hide/cannot ex. finder etc. i would post right ow but BTT just blew the fuck up and its not eunning and lost everything its a mess right ow all because i upgradeed to newest mac beta last night. so hopefully i can salavage this and get back to normal and ill post it-the new an improved versins

Make a copy of ~/Library/Application Support/BetterTouchTool before trying any recovery steps.

Which macOS beta are you on?

the newest developer beta 26.5t it was the strangest thing happened once upon reboot: when BTT opened an error dialog opened stating (IIRC cant recall exactly) that my preset or store files were too old and incompatible with the current BTT version and then iBTT would terminate.

Thanks for the reminder, always save a copy of the folder and put it on desktop etc. From looking inside the store files were older. I think i was able to either find some files in the trash and restore them or can’t remember all I kow is I luckily got it back to pretty much were I was. First I had to delete all the old store whm etc files just so I could start BTT and then twent from there and luckily somehpw was able to recover the files and do a restore from backup inside of BTT.

Ill post preset in a few

Hi everyone,

I’ve been using the original Windows-like Dock minimize toggle preset and made an updated Version 2 that I wanted to share back with the community.

The goal is the same: make macOS Dock clicks behave more like the Windows taskbar. Clicking an app icon can activate, restore, or minimize the app depending on its current state.

In Version 2 I’ve made a few improvements:

  • Cleaned up the preset structure and removed duplicate trigger/action blocks.
  • Renamed the main trigger from toogleminimize to toggleDockMinimize.
  • Improved app detection using bundle ID, app path, app URL, title, description, and app name fallbacks.
  • Added better handling for apps with no windows, one window, or multiple windows.
  • Added support for restoring all minimized windows when needed.
  • Added safer activation/reopen logic for apps that are not running or have not created windows yet.
  • Added duplicate-click protection to avoid repeated accidental invocations.
  • Added fallback behavior if the script cannot complete normally.
  • Added special handling around Mission Control / Dock focus states.
  • Improved minimize behavior by trying to use the actual macOS minimize button action first, which should preserve the native animation where possible.

One note: in my setup, 1 finger tap on Dock icons works because I have that configured at the macOS/system level. The preset itself is focused on normal left-click over Dock icons. If you want the 1 finger tap behavior inside BetterTouchTool, you can add that trigger manually and point it to the same named trigger, or you can enable/configure tap-to-click at the system level like I have.

Thanks to the original preset author and to yw4z’s Enhanced Dock for macOS for the inspiration.

do you have a version to share? perhaps a link to download your version? I also have updated version been lagging on uploading a preset myself. Ill post soon. Look forward to seeing your version

Hey I'm waiting for my preset to be accepted and then i'll post the link!

Hey just shared the link, let me know how it is or if there are any problems.
Cheers

yah I tried it out. Works great. Better than the original. No point to upload mine but I will say at the very least people if they dont want to use yours for some reason they should at least change the original workflow and the IF THEN structure it uses-fixing that up takes likes a couple seconds makes the action work much better. Only thing I didnt totally like was your script automatically minimizes ALL windows upon first/1 tap. Sometimes i want that other times not so much. Mine only minimizes frontmost window on 1at tap and 1 window min everytime but if you want to toggle minimize all i have a separate trigger 1 finger tap but FN being held along with the tap to min all windows.

So instead of sharing another version of same thing basically I upload a action I use together with the action above but it hide/unhides the the app instead of toggling minimize. Way i have it setup is 1 Finger Tap on Dock Icon to toggle minimize application and 1 Finger Click on Dock icon to toogle hide action on application. Also the script does have a fallback function for apps unable hide and thus triggers them to minimize instead.

I included the preset to download aswell as an applescript you can use

-- Enhanced Dock Click Handler for BetterTouchTool (Improved)
-- Smart toggle for single-window apps, default-like behavior for multi-window apps

on run
try
set appName to "{appName}"
if appName is missing value or appName is "" or appName is "{appName}" then return

	tell application "System Events"
		if not (exists process appName) then
			-- Not running: let normal Dock launch behavior happen (or do nothing in BTT context)
			return
		end if
		
		tell process appName
			set appIsHidden to (visible is false)
			set appIsFrontmost to frontmost
			
			-- Standard windows only
			set standardWindows to {}
			try
				set standardWindows to (windows where subrole is "AXStandardWindow")
			end try
			set windowCount to (count of standardWindows)
			
			if windowCount is 1 then
				set theWindow to item 1 of standardWindows
				my handleSingleWindow(appName, theWindow, appIsFrontmost, appIsHidden)
				
			else if windowCount is 0 then
				-- No standard windows: activate app (reopen behavior depends on app)
				my activateApp(appName)
				
			else
				-- Multi-window app: keep behavior simple/predictable
				if appIsHidden then set visible to true
				my activateApp(appName)
			end if
		end tell
	end tell
	
on error errMsg number errNum
	-- Optional debug:
	-- log "Dock Handler Error: " & errMsg & " (" & errNum & ")"
	try
		if appName is not missing value and appName is not "" then my activateApp(appName)
	end try
end try

end run

on handleSingleWindow(appName, theWindow, appIsFrontmost, appIsHidden)
tell application "System Events"
set isMinimized to false
try
set isMinimized to (value of attribute "AXMinimized" of theWindow)
end try

	set isFullScreen to false
	try
		set isFullScreen to (value of attribute "AXFullScreen" of theWindow)
	end try
	
	if isMinimized then
		my setMinimized(theWindow, false)
		my raiseAndFocus(appName, theWindow)
		
	else if appIsHidden then
		set visible of process appName to true
		my raiseAndFocus(appName, theWindow)
		
	else if isFullScreen then
		if appIsFrontmost then
			-- Optional behavior: if already frontmost fullscreen, minimize
			-- Some apps dislike toggling fullscreen via AX; fallback safely
			try
				set value of attribute "AXFullScreen" of theWindow to false
				delay 0.35
			end try
			my setMinimized(theWindow, true)
		else
			my raiseAndFocus(appName, theWindow)
		end if
		
	else if appIsFrontmost then
		my setMinimized(theWindow, true)
		
	else
		my raiseAndFocus(appName, theWindow)
	end if
end tell

end handleSingleWindow

on raiseAndFocus(appName, theWindow)
try
tell application "System Events"
set frontmost of process appName to true
try
perform action "AXRaise" of theWindow
end try
end tell
on error
my activateApp(appName)
end try
end raiseAndFocus

on setMinimized(theWindow, shouldMinimize)
try
tell application "System Events"
set value of attribute "AXMinimized" of theWindow to shouldMinimize
end tell
on error
-- Fallback: raise if unminimizing failed
if shouldMinimize is false then
try
tell application "System Events" to perform action "AXRaise" of theWindow
end try
end if
end try
end setMinimized

on activateApp(appName)
try
tell application id (my bundleIDForApp(appName)) to activate
on error
try
tell application appName to activate
end try
end try
end activateApp

on bundleIDForApp(appName)
try
tell application "System Events" to return bundle identifier of application process appName
on error
return missing value
end try
end bundleIDForApp

Because your dockminimize script functions well-there is no reason for me to post mine so instead I will post another script I use in congunction with the minimizeapp script: click dock app to hide appliation. I use 1 finger tap on a dock icon to minimize the app and use 1 finger click on the dock icon to hide/unhide the application  (if hiding is not possible with app it has a fallback function that will auto minimize it because some apps are unable to hide)

Enjoy to use just copy the json code and then paste in BTT when in the touchpad section

-- Enhanced Dock Click Handler for BetterTouchTool (Improved)
-- Smart toggle for single-window apps, default-like behavior for multi-window apps

on run
	try
		set appName to "{appName}"
		if appName is missing value or appName is "" or appName is "{appName}" then return
		
		tell application "System Events"
			if not (exists process appName) then
				-- Not running: let normal Dock launch behavior happen (or do nothing in BTT context)
				return
			end if
			
			tell process appName
				set appIsHidden to (visible is false)
				set appIsFrontmost to frontmost
				
				-- Standard windows only
				set standardWindows to {}
				try
					set standardWindows to (windows where subrole is "AXStandardWindow")
				end try
				set windowCount to (count of standardWindows)
				
				if windowCount is 1 then
					set theWindow to item 1 of standardWindows
					my handleSingleWindow(appName, theWindow, appIsFrontmost, appIsHidden)
					
				else if windowCount is 0 then
					-- No standard windows: activate app (reopen behavior depends on app)
					my activateApp(appName)
					
				else
					-- Multi-window app: keep behavior simple/predictable
					if appIsHidden then set visible to true
					my activateApp(appName)
				end if
			end tell
		end tell
		
	on error errMsg number errNum
		-- Optional debug:
		-- log "Dock Handler Error: " & errMsg & " (" & errNum & ")"
		try
			if appName is not missing value and appName is not "" then my activateApp(appName)
		end try
	end try
end run

on handleSingleWindow(appName, theWindow, appIsFrontmost, appIsHidden)
	tell application "System Events"
		set isMinimized to false
		try
			set isMinimized to (value of attribute "AXMinimized" of theWindow)
		end try
		
		set isFullScreen to false
		try
			set isFullScreen to (value of attribute "AXFullScreen" of theWindow)
		end try
		
		if isMinimized then
			my setMinimized(theWindow, false)
			my raiseAndFocus(appName, theWindow)
			
		else if appIsHidden then
			set visible of process appName to true
			my raiseAndFocus(appName, theWindow)
			
		else if isFullScreen then
			if appIsFrontmost then
				-- Optional behavior: if already frontmost fullscreen, minimize
				-- Some apps dislike toggling fullscreen via AX; fallback safely
				try
					set value of attribute "AXFullScreen" of theWindow to false
					delay 0.35
				end try
				my setMinimized(theWindow, true)
			else
				my raiseAndFocus(appName, theWindow)
			end if
			
		else if appIsFrontmost then
			my setMinimized(theWindow, true)
			
		else
			my raiseAndFocus(appName, theWindow)
		end if
	end tell
end handleSingleWindow

on raiseAndFocus(appName, theWindow)
	try
		tell application "System Events"
			set frontmost of process appName to true
			try
				perform action "AXRaise" of theWindow
			end try
		end tell
	on error
		my activateApp(appName)
	end try
end raiseAndFocus

on setMinimized(theWindow, shouldMinimize)
	try
		tell application "System Events"
			set value of attribute "AXMinimized" of theWindow to shouldMinimize
		end tell
	on error
		-- Fallback: raise if unminimizing failed
		if shouldMinimize is false then
			try
				tell application "System Events" to perform action "AXRaise" of theWindow
			end try
		end if
	end try
end setMinimized

on activateApp(appName)
	try
		tell application id (my bundleIDForApp(appName)) to activate
	on error
		try
			tell application appName to activate
		end try
	end try
end activateApp

on bundleIDForApp(appName)
	try
		tell application "System Events" to return bundle identifier of application process appName
	on error
		return missing value
	end try
end bundleIDForApp


Hey thanks for your message and for trying it out. I'm please you agree with the improvements, I'm a one window kind of guy so it never occurred to me to have those minimise all/solo features.
I think they're good ideas, I could add them to the preset when I get some time.

Based on your research I have tried to make a native action out of this. If it works correctly it should be slightly more performant than the script solution

It is included in 6.603