Use Case
- Use anytime you want to quickly move all of your windows to the primary (internal) screen, like during an emergency power down.
UPDATED: 2021-02-24 11:31 GMT-6
Change Log
Ver 2.1 Changes 2021-02-24
- Fix error caused by a change in the macOS
- Error:
Can’t get origin of {{0.0, 0.0}, {3440.0, 1415.0}}.
- Error:
VER 2.0 Changes
- Script now searches for ALL Apps and ALL Windows, whether they are background or not, visible or not.
- Added optional display of list of all windows that were found (enable the last Action).
Example of All Window list
Shows window coordinates BEFORE any were moved.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MACRO: Move ALL Windows to Primary Screen
-~~~ VER: 2.1 2021-02-24 ~~~
Requires: KM 8.2.4+ macOS 10.11 (El Capitan)+
(Macro was written & tested using KM 9.0+ on macOS 10.14.5 (Mojave))
DOWNLOAD Macro File:
Move ALL Windows to Primary Screen.kmmacros
Note: This Macro was uploaded in a DISABLED state. You must enable before it can be triggered.
ReleaseNotes
Author.@JMichaelTX
PURPOSE:
- Move ALL Windows to Primary (Internal) Screen
HOW TO USE:
- Trigger this macro
.
- All Windows NOT on the Primary Screen will be moved to the Primary Screen
- The Top, Left Position will be offset (see below) to stagger the windows
- The Window Height will be adjusted so that the Window Bottom is NOT below the Screen Bottom.
- A Notification (from the Script) will be made when the script/macro completes.
NOTE: To see list of all windows, with coordinates before the move, ENABLE the last Display Text Action.
MACRO SETUP
- There are no Actions designed for changes by end user.
- However, you may adjust these Properties in the Script
--- OFFSETS Used When Moving Windows ---
property ptyOffsetX : 20
property ptyOffsetY : 40 - You may also ENABLE the last Action, Display Text, to see a list of all Windows before the move.
- You are responsible for running the Macro, not me.
.
- You are responsible for running the Macro, not me.
- Assign a Trigger to this maro. I prefer to put it in a Group with a Palette, and assign "M" as the trigger.
- Move this macro to a Macro Group that is only Active when you need this Macro. This is probably a Global Group, in this case.
- ENABLE this Macro.
TAGS: @Screen @Display @Window @Move @AS
USE AT YOUR OWN RISK
- While I have given this limited testing, and to the best of my knowledge will do no harm, I cannot guarantee it.
- If you have any doubts or questions:
- Ask first
- Turn on the KM Debugger from the KM Status Menu, and step through the macro, making sure you understand what it is doing with each Action.
AppleScript to Move All Windows
property ptyScriptName : "Move Windows to Main Screen"
property ptyScriptVer : "2.1" -- CHG formulas for extracting screen coordinates
property ptyScriptDate : "2021-02-24" # Search for ALL Apps
property ptyScriptAuthor : "JMichaelTX"
property LF : linefeed
(*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
REQUIRED:
1. macOS El Capitan 10.11.6+
(may work on Yosemite 10.10.5, but no guarantees)
Local: /Users/Shared/Dropbox/SW/DEV/KM/Scripts/Move Windows to Main Screen V2.1.scpt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*)
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions
--- OFFSETS Used When Moving Windows ---
property ptyOffsetX : 20
property ptyOffsetY : 40
set scriptResults to "TBD"
try
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set frontApp to path to frontmost application as text -- use for dialogs
--- GET COORDINATES OF PRIMARY VISIBLE SCREEN ---
-- (all windows to the right, or to the left, of this will be moved)
set primaryScreenVisibleFrame to current application's NSScreen's screens()'s firstObject()'s visibleFrame()
set primaryScreenLeft to (item 1 of item 1 of primaryScreenVisibleFrame)
set primaryScreenRight to (primaryScreenLeft) + (item 1 of item 2 of primaryScreenVisibleFrame)
set primaryScreenTop to (item 2 of item 1 of primaryScreenVisibleFrame)
set primaryScreenBottom to (primaryScreenTop) + (item 2 of item 2 of primaryScreenVisibleFrame)
(*
--- ALTERNATE METHOD Using KM ---
tell application "Keyboard Maestro Engine"
set AppleScript's text item delimiters to ","
set primaryScreenVisibleFrame to text items of (process tokens "%ScreenVisible%Main%")
set primaryScreenRight to item 3 of mainScreenFrame
end tell
*)
--- GET ALL VISIBLE APPS ---
tell application "System Events"
set appNameList to (name of every application process)
end tell
--log " App List: " & (appNameList as text)
set iWin to 0
--- LOOP THROUGH EACH APP ---
set logStr to "Left, Top, Width, Height ┃ App ┃ WinRole ┃ Win Title" & LF & LF
display notification "START Search for Windows"
repeat with oAppName in appNameList
set appName to contents of oAppName
-----------------------------------------------------
tell application "System Events" to tell application process appName
-----------------------------------------------------
set winCount to count of windows
--display notification " App: " & appName & " # of Windows: " & winCount
repeat with iW from 1 to winCount
set oWin to window iW
tell oWin
set winTitle to title
set {winLeft, winTop} to position
set {winWidth, winHeight} to size
set winBottom to winTop + winHeight
if (((winLeft > primaryScreenRight) or ¬
(winLeft < primaryScreenLeft))) then
set logStr to logStr & my logWin({position & size & space & appName & space & role & space & title}, " ⬅︎⬅︎ ") & LF
--- MOVE WINDOW ---
set iWin to iWin + 1
--- ADD OFFSETS to POSITION ---
set newXPos to primaryScreenLeft + (ptyOffsetX * iWin)
set newYPos to primaryScreenTop + (ptyOffsetY * iWin)
set position of oWin to {newXPos, newYPos}
--- MAKE SURE WIN BOTTOM DOES NOT EXCEED SCREEN BOTTOM ---
set newBottom to newYPos + winHeight
if (newBottom > primaryScreenBottom) then set newBottom to primaryScreenBottom
set newHeight to newBottom - newYPos
set size of oWin to {winWidth, newHeight}
else
set logStr to logStr & my logWin({position & size & space & appName & space & role & space & title}, " ") & LF
end if
end tell
end repeat -- on each window
end tell -- "System Events" --> appName
end repeat -- oAppName in appNameList
if (iWin > 0) then
set msgStr to (iWin as text) & " Window(s) MOVED"
else
set msgStr to "NO Windows Were Found to Move."
end if
set msgTitleStr to ptyScriptName
display notification msgStr with title msgTitleStr sound name "Tink.aiff"
set scriptResults to "OK" & LF & msgStr & LF & LF & logStr
--~~~~~~~~~~~~~ END TRY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on error errMsg number errNum
if errNum = -128 then ## User Canceled
set errMsg to "[USER_CANCELED]"
end if
set scriptResults to "[ERROR]" & return & errMsg & return & return ¬
& "SCRIPT: " & ptyScriptName & " Ver: " & ptyScriptVer & return ¬
& "Error Number: " & errNum
end try
--~~~~~~~~~~~~~~~~END ON ERROR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- RETURN THE RESULTS TO THE KM EXECUTE SCRIPT ACTION ---
return scriptResults
--~~~~~~~~~~~~~~~ END OF MAIN SCRIPT ~~~~~~~~~~~~~~~~~~~
on logWin(pListOfProp, pPrefixStr)
local logWinStr
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ", "
set logWinStr to pPrefixStr & (pListOfProp as text)
set AppleScript's text item delimiters to astid
set logWinStr to my changeString(", ,", " ┃ ", logWinStr)
return logWinStr
end logWin
on changeString(pSearchForStr, pReplaceWithStr, pSourceStr)
local item_list, changedStr, astid
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to the pSearchForStr
set the item_list to every text item of pSourceStr
set AppleScript's text item delimiters to the pReplaceWithStr
set changedStr to the item_list as string
set AppleScript's text item delimiters to astid
return changedStr
end changeString