66

I know it's just a pet peeve, but I hate it that Mac OS X's Preview.app stays open when it has no windows open. Is there any way to make it close when its last window is closed?

Since I don't see any option inside Preview to make that happen, I imagine that the answer might be applicable to other programs that have similar … idiosyncrasies.

I realize that this is not outside the OS's interface guidelines. That is, I recognize that this isn't a bug that will be fixed. I'm wondering if there is some way to automatically close selected GUI applications that have no windows open.

wfaulk
  • 6,307

8 Answers8

28

Try RedQuits:

RedQuits is there to help if you have ever tried to close an application with its red button and wondered why it is still open. With RedQuits, all programs now quit when there's only one window left for that program. If you want to quit and close all open windows of a program, just uncheck "Quit only when 1 window is left for that app." in the preferences.

Daniel Beck
  • 111,893
msaied
  • 296
23

In short: No.

--Answer stops here. Everything following is just my attempt to explain why.

What you are experiencing is the Mac philosophy of how applications should behave. Those who are closed after the last window dissapears are not behaving to Mac Interface Guidelines (though there are a lot out there). // Edit: This is not entirely correct, see posts below.

It has been that way since the very first Mac System (in 1984). I guess it'll stay with us for another 25 years to come. Maybe app devs will allow us to set that in the preferences.

Until then it helps getting used to Command-Q (the Apple key and q) to quit each and every app - and Command-W for just the active window.

Wolf
  • 2,593
3

The automatic termination feature introduced in 10.7 partially addresses that for some applications.

If you open Preview, open at least one window in it, close all windows, and switch to another application, Preview is hidden from the Dock and application switcher. If you look at Activity Monitor, the process is still running and uses memory, but there might be some changes in how the process is managed.

The Mac App Programming Guide says that processes are actually terminated, so there might be something I'm missing.

  • Automatic termination eliminates the need for users to quit an app. Instead, the system manages app termination transparently behind the scenes, terminating apps that are not in use to reclaim needed resources such as memory.

[...]

Automatic termination transfers the job of managing processes from the user to the system, which is better equipped to handle the job. Users do not need to manage processes manually anyway. All they really need is to run apps and have those apps available when they need them. Automatic termination makes that possible while ensuring that system performance is not adversely affected.

Lri
  • 42,502
  • 8
  • 126
  • 159
3

I wrote an AppleScript application to do this for you.

In brief, it checks what applications are open, gives you the option to whitelist apps to be excluded from auto-quit, then every 60 seconds, quits all applications (that it can, due to limitations).

To alter the whitelist while it's running, click the icon in the dock for the selection dialog to reappear.

To quit, right click the Dock icon and choose "Quit"

AppleScript source and Application: http://files.me.com/kioarthurdane/6kjl9k

dotHTM
  • 1,519
2

Update 2022

RedQuits (http://www.carsten-mielke.com/redquits.html) works fine on macOS Monterey (Version 12.5.1).

  • Install and enable all three checkboxes:

enter image description here

  • Enable RedQuits in privacy > accessibility settings:

enter image description here

GorvGoyl
  • 247
2

Another free small and simple app, Quitter, displays an X icon in the traybar which acts just like the closing button under Windows.

Andreas
  • 21
1

Override the following method in NSApplicationDelegate (which normally returns NO):

-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSapplication*)sender
{
return YES;
}
1

download hammerspoon and add this to your ~/.hammerspoon/init.lua


-- last window quit program --

-- Initialize the watcher and menubar local windowWatcher = nil local menubar = nil

-- List of apps to exclude from auto-quitting local excludedApps = { "Hammerspoon", "Spotlight", "Finder" -- It's generally a good idea to exclude Finder as well }

-- Function to check if an app should be excluded local function isExcluded(appName) for _, excludedApp in ipairs(excludedApps) do if appName == excludedApp then return true end end return false end

-- Function to check and quit the application if the last window is closed local function checkAndQuitApp(window) local app = window:application() if not app then return end

local appName = app:name()

-- Don't quit excluded apps
if isExcluded(appName) then return end

-- Check if the application has any windows left
local allWindows = app:allWindows()

-- If there are no windows left, quit the app
if #allWindows == 0 then
    -- Delay the quit operation slightly to ensure the window closes first
    hs.timer.doAfter(0.1, function()
        app:kill()
    end)
end

end

-- Function to start the watcher local function startWatcher() if windowWatcher then windowWatcher:stop() end

windowWatcher = hs.window.filter.new(true)
windowWatcher:subscribe(hs.window.filter.windowDestroyed, checkAndQuitApp)

end

-- Function to create menu local function createMenu() local menuItems = { {title = "Last Window Quit Enabled", checked = true, fn = function() end}, {title = "-"}, -- Separator {title = "About Last Window Quit", fn = function() hs.alert.show("Last Window Quit: Quits apps when closing the last window (except excluded apps)") end}, {title = "-"}, -- Separator {title = "Quit Menu", fn = function() if menubar then menubar:delete() menubar = nil end end} }

if not menubar then
    menubar = hs.menubar.new()
end
menubar:setTitle("LWQ")  -- LWQ for "Last Window Quit"
menubar:setMenu(menuItems)

end

-- Function to toggle the menubar local function toggleMenubar() if menubar then menubar:delete() menubar = nil hs.alert.show("Last Window Quit menubar removed") else createMenu() hs.alert.show("Last Window Quit menubar restored") end end

-- Start the watcher when the script loads startWatcher()

-- Create the menu initially createMenu()

-- Bind hotkey to toggle menubar hs.hotkey.bind({"alt", "shift"}, "Q", toggleMenubar)

-- Log that the script has loaded print("Last Window Quit script loaded")