How to Hide All Windows of an App Other Than the Front One

This is very hard, at least for me. I have spent many hours on this, but have learned a lot.

Here is a general purpose script that should work well with all apps.
I have tested it with:
• Finder
• Apple Mail
• Outlook 2011
• Evernote
• Chrome
• Safari

It is NOT perfect. There could be issues with Finder if you have actual Finder windows with the same name.

If you have any ideas on how to improve, or find issues, please post.

Minimize All App Windows Except Frontmost

(*
===============================================================================
  Minimize All App Windows Except Frontmost
===============================================================================

VER:   1.0    LAST UPDATE:   2016-04-09

PURPOSE:
  • ============================================================================
  Minimize All App Windows Except Frontmost

AUTHOR:    JMichaelTX
          Find any bugs/issues or have suggestions for improvement?
          Contact me via PM or at blog.jmichaeltx.com/contact/

REQUIRED:
  1.  Mac OS X Yosemite 10.10.5+
  2.  Mac Applications -- NONE are required, but this has been tested with:
        • Finder
        • Apple Mail
        • Outlook 2011
        • Evernote
        • Chrome
        • Safari
        
  3.  INTERNAL FUNCTIONS:
      • removeDups(pList)

REF:  The following were used in some way in the writing of this script.
  1.  
===============================================================================
   
*)
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "System Events"
  
  --- GET FRONTMOST APP ---
  --    CAUTION:
  --      1. Some commands do NOT work when using tell application with 
  --        a variable instead of explicit text
  --      2. Different Apps have different commands to minimize a window
  --      3. Thus, I had to use System Events with a UI keyboard command
  --    If you know of a better way, please let me know
  
  set frontAppName to item 1 of (get name of processes whose frontmost is true)
  
  tell process frontAppName
    
    set numWin to count of windows
    
    --- GET LIST OF WINDOW NAMES ---
    --    CAUTION:
    --      1. Some apps, like the Finder, can have different windows with the same name
    --      2. Some apps, like the Finder, report duplicate windows in error
    
    set winTitleList to title of every window
    set winTitleList to my removeDups(winTitleList) -- needed for Finder windows
    
    --- Remove 1st Window (the current Frontmost) from List ---
    set winTitleList to (items 2 thru -1 of winTitleList)
    
    repeat with windowTitle in winTitleList
      -- Select/Activate Each Window to Make Frontmost --
      click menu item windowTitle of menu 1 of menu bar item "Window" of menu bar 1
      delay 0.1
      
      -- Minimize the Window --
      keystroke "m" using command down -- this is same as CMD-M
    end repeat
    
  end tell
end tell


--~~~~~~~~~~~~~~~~~~~~~~~ END OF MAIN SCRIPT ~~~~~~~~~~~~~~~~~~~~

on removeDups(pList)
  local newList
  set newList to {}
  repeat with iItem from 1 to count pList
    set itemStr to item iItem of pList
    if itemStr is not in newList then set end of newList to itemStr
  end repeat
  return newList
end removeDups

Hey Tom,

There's no perfect way to make that generic, but JM has the general idea.

-Chris

Okay, I've fiddled with this quite a bit:

------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2016/04/10 06:00
# dMod: 2016/04/13 06:37
# Appl: System Events
# Task: Minimize all Windows Except the Front One in the Front App.
# Tags: @Applescript, @Script, @System_Events, @Minimize, @Windows
------------------------------------------------------------

tell application "System Events"
  tell (first process whose frontmost is true)
    set winList to windows whose subrole is "AXStandardWindow"
    
    if length of winList > 1 then
      set winList to rest of winList
      
      repeat with theWindow in winList
        try
          tell theWindow to set value of attribute "AXMinimized" to true
        end try
      end repeat
      
    end if
    
  end tell
end tell
------------------------------------------------------------

So far it's worked with every app I've tried it on.

-Chris

Edited 2016/04/13 06:38 CST to fix the flaw Alain noticed below.

2 Likes

I already expected something along the lines when I saw your other script :wink:

Seems to work nicely. Except in Firefox the frontmost window gets minimized.

Hey Tom,

Hmm... Not on my system. (OSX 10.11.4)

Firefox 45.0.1

Tested with Script Debugger, FastScripts, and Keyboard Maestro.

Not sure what might be happening at your end.

-Chris

I’m investigating. Sometimes it works in FF, sometimes the front window gets minimized. It seems that it depends if I’ve done something in the front window (e.g. adding a tab).

Can you reproduce: Close all FF windows and close FF. Start FF. Type 3 × ⌘N. Launch the macro. -> The window that stays on screen is the oldest one.

Hey Tom,

That only seems to happen here when none of the windows have any content.

What about at your end?

-Chris

No, they do have content (they start with the default URL (“Homepage”)). The frontmost window only gets “recognized” as frontmost after I’ve changed the URL or opened another tab.

Same FF and OS version here.

But I don’t think it’s worth investigating much in FF abnormalities…

Thanks Christopher (and @JMichaelTX) for this script.

I've just fiddled a very little bit to avoid minimizing a solitary window:

tell application "System Events"
  tell (first process whose frontmost is true)
    set winList to windows whose subrole is "AXStandardWindow"
    
    if length of winList > 1 then
      set winList to rest of winList
      repeat with theWindow in winList
        try
          tell theWindow to set value of attribute "AXMinimized" to true
        end try
      end repeat
    end if
    
  end tell
end tell

--Alain

2 Likes

Nice script, Chris.
Thanks.

Alain, great catch and fix. :+1:
Thanks for sharing.

I've tested your script and it seems to work.

Interestingly, collapsed windows apparently have subrole AXUnknown or AXDialog (for some reason), so this doesn’t work for unminimizing all of an application’s windows. See also Minimize all windows of an application.

Eh?

Oh, that's what mine looked like before I “optimized” it.

Good catch.

-Chris

I had an engineering boss once, who often said:

'Better' is the enemy of 'good enough'

:wink:

I didn't always agree with that, since it depends on just how good "good enough" is.

Hey Folks,

Okay, let's try doing that with Keyboard Maestro's native actions.

-Chris

(Edited 2016/04/15 07:49 CST – moved delete-variable action to end.)


Minimize Windows Other than the Frontmost One in the Front App.kmmacros (4.8 KB)

2 Likes

Sometimes the last tweak is one too many (especially when you're tired).

-Chris

Christopher, is the “%Delete% Variable” Action could not be simply delete :wink: or what is the meaning?
Nice moved at the macro end :slight_smile:
–Alain

Hey Alain,

You're right. The delete-variable action is better off at the end.

Fixed.

-Chris

It's very useful for me. If possible recover the Minimize (show) the windows, after minimized them?