Hold Cmd-Q to Quit as a system-wide action?
I like that Chrome asks you to hold "Cmd-Q" to quit. Is there a way to do this for every app on a Mac?
You can do this by installing and running Hammerspoon, then including the following Lua code in the Hammerspoon configuration file (.hammerspoon/init.lua
):
-- config: number of seconds to hold Command-Q to quit application
cmdQDelay = 2
cmdQTimer = nil
cmdQAlert = nil
function cmdQCleanup()
hs.alert.closeSpecific(cmdQAlert)
cmdQTimer = nil
cmdQAlert = nil
end
function stopCmdQ()
if cmdQTimer then
cmdQTimer:stop()
cmdQCleanup()
hs.alert("quit canceled",0.5)
end
end
function startCmdQ()
local app = hs.application.frontmostApplication()
cmdQTimer = hs.timer.doAfter(cmdQDelay, function() app:kill(); cmdQCleanup() end)
cmdQAlert = hs.alert("hold to quit " .. app:name(), true)
end
cmdQ = hs.hotkey.bind({"cmd"},"q",startCmdQ,stopCmdQ)
Change the value of cmdQDelay
to fit your preference.
A brief explanation:
The final line tells Hammerspoon to intercept any presses of Command-Q. It will run the lua function named startCmdQ
when the key is pressed, and stopCmdQ
when it is released.
startCmdQ
takes a note of the foreground app, then starts a timer. If the timer times out, the function given as argument to the timer is called. It kills the app (really, asks it to quit) and cleans up after the action.
stopCmdQ
stops the timer if it is still running, so the application is not quit after all. It too cleans up afterwards.
The action is accompanied by alerts to let you know what is going on.
Edit: Once this is installed and active, you can turn it off by running cmdQ:disable()
in the hammerspoon console. Turn it back on with cmdQ:enable()
. And if you want to excempt some apps from the delay treatment, you can add a test for those apps in the startCmdQ
function, opting to run app:kill()
immediately instead of starting the timer.
Edit the second: A word of caution. This will let you quit the Finder. Don't panic, though. The easiest way to relaunch Finder is to click on its icon in the Dock. Or you can use Spotlight: Open it via the magnifying glass icon in the menu bar or its keyboard shortcut and type “Finder.app”, then return. (You will only need to type a few letters, as Spotlight will fill in the rest for you). You can also relaunch Finder by running the command hs.application.open("Finder")
in the hammerspoon console, or open -a Finder
in a Terminal window, if you happen to have Terminal running.
If you want this behavior because you are afraid you'll accidentally press ⌘Q while trying to press something similar (usually ⌘W or perhaps ⌘Tab), then you can remap the ⌘Q shortcut to a similar but harder-to-press shortcut, let's say to ⌥⌘Q.
To do this, you'll need either 1) a way to remap ⌘Q to ⌥⌘Q, or 2) block ⌘Q and set ⌥⌘Q to quit apps.
Method 1: remap ⌘Q to ⌥⌘Q
Method 1a: Using System Preferences
- Go to System Preferences > Keyboard > Shortcuts > App Shortcuts
- For each app individually you want to do this in, create a shortcut which has trigger ⌥⌘Q and action
Quit x
where x is the name of the app. For example, for Safari I'd write "Quit Safari" (without quotes). Note that if this isn't working you might need to check what the name of the app is in the menu bar item.
Method 1b: Using Karabiner Elements or something similar
This should remove the limitation of manually having to set the shortcut for all apps. This is likely possible with the powerful tool Karabiner Elements but unfortunately I'm not fluent enough in it to say how.
As mentioned by Harald Hanche-Olsen in the comments, Hammerspoon may also let you do this, although you will need to look into it a bit more.
Method 2: block ⌘Q and set ⌥⌘Q to quit
The only reason I'm including a third-party app here is that it should be possible to do with using BTT globally, but due to a bug (?) you'll need to do this individually for all apps.
- Download and install BetterTouchTool (paid but has a 45-day trial)
- Create a global keyboard shortcut with ⌘Q set to do nothing
- Create a global keyboard shortcut with ⌘Q set to the action Menu Bar Item, and set this as the description:
x;Quit x
where x is the name of the app. Again note you might need to check what it actually says in the app you want to do this for.
I was hoping you could globally do this by using a wildcard in step 3 for the the first-level menu bar item, which would eliminate the need to explicitly type the app name in. In this case, you could use *;Quit *
as the description. However, this doesn't seem to be possible for some reason.
No, there is no way to coax all other applications into the hold-cmd-Q-for-couple-of-seconds-to-quit behavior.
Apple controls the apple apps and the SDK and they don’t implement this.
At best you could get a bunch of third party developers that like this idiom to all implement it.