Alternative way of managing window positions with alfred.app
Table of Contents
Introduction⌗
Dear reader, I’m about to inform you my upgraded setup how I manage my windows after making this post Managing window positions with apple script and alfred workflows.
As I had several apps managed on the previous setup, I wanted a bit more flexibility with it. My setups differ sometimes from eachother. Mainly I have a PLP setup, sometimes I work from just my macbook (Optionally with my iPad as second screen).
So I had a few reqruirements:
- Easy to add new apps to the setup
- Easy to support multiple layouts
- Abillity to reapply the position to a single app
Setup⌗
Knowing the position⌗
To know the position (bounds or pos & size) I have a script that will place the location of requested app in the clipboard. It is constructed as followed:
For scriptfilter with keyword ws pos
I use the following script.
tell application "System Events" to set theNames to name of processes whose background only is false
set appNameList to {}
set ignoreList to {"app_mode_loader"}
repeat with appName in theNames
if appName is not in ignoreList then
set end of appNameList to appName
end if
end repeat
-- Construct JSON output
set jsonArray to "{ \"items\": ["
repeat with i from 1 to count of appNameList
set appName to item i of appNameList
set jsonArray to jsonArray & "{\"title\": \"" & appName & "\", \"subtitle\": \"Get the bounds / pos & size of" & appName & "\", \"arg\": \"" & appName & "\"}"
if i is not equal to (count of appNameList) then
set jsonArray to jsonArray & ","
end if
end repeat
set jsonArray to jsonArray & "]}"
return jsonArray
This allows me to easily select the apps I want to get either the bounds
or pos
/ size
from.
But not all apps are always shown, such as Browser Apps. So I also have a keyword trigger on ws pos
that requires an argument.
The script that grabs the actual position of the requested app:
use framework "Foundation"
use scripting additions
on run argv
set theQuery to item 1 of argv
try
tell application theQuery
set appBounds to get the bounds of the front window
set resultString to "set appBounds to {" & (item 1 of appBounds) & ", " & (item 2 of appBounds) & ", " & (item 3 of appBounds) & ", " & (item 4 of appBounds) & "}"
end tell
on error errorMessage number errorNumber
tell application "System Events" to tell application process theQuery
set appPos to get position of window 1
set appSize to get size of window 1
set posString to "set appPos to {" & (item 1 of appPos) & ", " & (item 2 of appPos) & "}"
set sizeString to "set appSize to {" & (item 1 of appSize) & ", " & (item 2 of appSize) & "}"
set resultString to posString & "\n" & sizeString
end tell
end try
return resultString
end run
The above script will output the required variables and values for the requested app. Which in turn can be copy & pasted into the script to position said app.
output:
# Bounds
set appBounds to {1088, 406, 2719, 1461}
# Pos & Size
set appPos to {-2160, 1436}
set appSize to {2160, 1420}
And the output should be passed to a transform
to trim the whitespaces and afterwards to Copy to Clipboard
.
Placing apps⌗
To place apps at the wanted location we just need to call either one of the below script.
If the app supports bounds, you’ll know this via the contents in the clipboard provided by ws pos ...
set appBounds to {3218, -38, 5351, 1284}
tell application "System Events"
try
set bounds of the front window of application "Safari" to appBounds
end try
end tell
Otherwise for size & pos:
set appPos to {-2160, -959}
set appSize to {2160, 963}
tell application "System Events"
try
tell process "Discord"
set position of window 1 to appPos
set size of window 1 to appSize
end tell
end try
end tell
The above scripts are used in the larger workflow to position each invividual app.
Alfred Workflows⌗
ws pos⌗
ws place⌗
This is the main workflow, which to me is maintainable. I can update the List Filter
to add or remove workspace layouts. And / or remove single apps placement scripts.
With the Keyword: ws place ...
I can select a singular app to be repositioned according to the provided details.
Which are also corolated to the if/else
blocks presented with a1-a10
below.
And with the List Filter: ws place
It’ll present to me a list of configured layouts. Which is attached to a junction
which will invoke all attached scripts.
In my workflow, I include a junction
after each set of app layouts that points to a Play sound
action. This is helpful as it plays a sound when the task is complete, similar to the ws pos
mentioned earlier.
Note: The line ╌
between ipad
and the junction
block on the same plane to the right are connected.