@LawyerSteve:
If you like, I would be happy to export and share these macros.
Here is what I have done:
Firstly, this macro is the one that moves the three apps I referenced (Calendar, Things, Mail) to their appropriate positions. I have a two monitor setup, and trial and error was used to figure out the correct screen to use in KM, as there isn’t an easy way to figure this out programmatically.
Basically, what this does is:
- Figure out how many screens there are, and decide which screen to put the windows on. In this case, I make it screen 1 because that is the left hand most screen on my desk, but it was trial and error to figure this out.
- For each of the three apps, there are several steps:
- First, activate the app, and then pause until the app is running
- Execute an AppleScript to make sure that there is a window open for the app. The AppleScript differs for each app, so if you want to apply this to other apps, you may have to experiment in AppleScript to get a reliable script for that app.
- Execute my subroutine macro called “Sub: Set Front Window To Location”. This is really the guts of the process and is part of a series of subroutine macros that I use to position windows. This system assumes the screen is divided into rows and columns given by verticalGrid and horizontalGrid. The rows and columns are numbered started at 1. A window can be placed with its top left corner at any grid position. I can specify how many rows and columns to span with that window. This system allows me to be very flexible in putting windows into various places on the screen. The subroutine takes parameters for the Location of the top and left corners, the number of rows and columns, the number of rows and columns to span, and the screen to place the window on. The subroutine basically does the needed calculations to position the window.
The subroutine itself is given here:
What this basically does is:
- Check to make sure we gave a screen to put the window on. If we did not, I have a subroutine that figures out what screen the window is current on, and assumes we are just repositioning the window on that screen. I use that for various macros that use this subroutine to position a window on its current screen, so that those macros don’t have to explicit figure out what screen the window is on.
- Call my “Sub: Calculate Window Coordinates” to figure out where the window goes on that screen.
- Move the window there.
Finally, the macro to figure out window coordinates:
The majority of this macro is actually just checking the various inputs to make sure they all make sense, like you haven’t specified 0 or -5 rows or that the starting position plus the span doesn’t exceed the number of elements, so that the window will fit on the screen (you might not have wanted that; you might want to position a window on a screen so part of it hangs off, but I don’t, so I make sure that won’t happen).
The mean of this is at the end with formula like:
MAX(FLOOR(Local_screen.Left + (Local_screen.Width / Local_horizontalGrid * (Local_horizontalLocation-1)) + Local_margin), Local_screen.Left)
Which compute the various coordinates of the window.
There are other macros like the one that finds out the screen the front window is on (this is defined by the location of the top left corner, by looping through every screen and checking to see if the top left is on that window. A window is assumed to be “on” the screen where its top left corner is located.
There is also a subroutine that positions a window but takes the parameters as a JSON object instead of as individual arguments, as that is useful in some places.
I have a bunch of macros to put windows in various places like top half, left third, etc. Many of those are tied to buttons on my StreamDeck.
If this is of interest to you or anyone else I can post the macros for downloading. Caveat emptor. They work for me, but I cannot guarantee there are no bugs. Worst case, however, is that a window winds up in the wrong spot - I don’t see a way to hurt anything more than that.