Arrange displays

I am updating my window management macros

At home I have one two or three displays in use depending on what I am doing
For simplicity assume they are laid out left to right as
as
[small HP] [MacBook Internal with top menu bar] [Toshiba Wide screen]

Assume I have all three on and nicely arranged in system displays arrangement

If I turn say the HP off to watch a movie on the TOSHIBA, the "display arrangement" loses the plot

Now display positions are determined by the top left corner.

KM knows the size of each screen and its top left corner coordinates

My questions are
a: Is it possible to save the current screen positions/arrangement?

b: Is it possible to reinstate a previously saved position / arrangement?

1 Like

I've never thought of that problem before. Basically, you want to know the X/Y position of each monitor relative to each other. I'm reading the following page:

https://wiki.keyboardmaestro.com/function/SCREEN

... and I don't see anything there about getting their positions relative to each other. All I see are "sizes" and an "index" from left to right. (The Index tells you their left to right relative location, but not specific X/Y values.) There may be other people here who know of a way to fetch this data, but I can't see it.

Naturally, macOS has to save this "positional data" somewhere, and I'm quite sure you can read that data using the defaults command. If KM doesn't provide a function or token to obtain this data (and it doesn't seem to) you can fetch this data using the KM Execute Shell Script action which will use the defaults command. (More on this, below.)

Of course, there's also a fair chance that AppleScript contains functions to get you that data, but I don't know how to check that for you.

I once uploaded a macro on this site to help people discover the exact location of a system setting inside macOS using the defaults command. But even if I showed you that post, there would still be a lot of work interpreting that data.

You are asking for the ability to READ and WRITE data back into that configuration file. I'm not afraid to read data from that file, but writing to it is pretty dangerous, at least when it comes to critical data like monitor orientation. If I was trying to write a macro to do that for you, I might mess up my system, (or yours) making my monitors unusable, and requiring a reinstall of macOS.

If macOS has an API to allow apps to reorient their monitors, then programs like KM or AppleScript could pass that API to their users. But it's entirely possible that the only way Apple permits users to orient their monitors is by using the System Settings application and using the mouse. I'm just not sure. Someone else will have to chime in on that, because I don't have access to macOS API lists.

NEVERTHELESS, despite all those problems, there is another way to solve this. This method is perfectly safe, and not too difficult to program. And that is to use KM to launch the System Preferences app, go to the Displays pane, and literally drag the monitor to a different position. This is how you could "restore" a position. Your KM macro could have many different "positions" restorable. But there would be no way for a user of the macro to "save" a position. The only way to "save" a position is to write the code to "restore" it. Maybe that's good enough for you.

And that is to use KM to launch the System Preferences app, go to the Displays pane, and literally drag the monitor to a different position.

That is what I am currently doing and I am fed up with doing it, as there is no consistency in why it screws up.

I already have a debug that shows position etc, which I will publish properly in a couple of days

in essence it is a display window with

%Variable%Instance_dateandtimestamp_s%
Executing Macro: %ExecutingThisMacro%
From Macro: %ExecutingMacro%
Comment: %Variable%Instance_comment_s%

Number of screens Screencount is >> %Calculate%SCREENCOUNT()%

(NB. 1080p = 1920x1080)

FRONT Left, Top, Width, Height
%Calculate%SCREENVISIBLE(Front, Left)% %Calculate%SCREENVISIBLE(Front, Top)% %Calculate%SCREENVISIBLE(Front, Width)% x %Calculate%SCREENVISIBLE(Front, Height)%

MAIN Left, Top, Width, Height
%Calculate%SCREENVISIBLE(Main, Left)% %Calculate%SCREENVISIBLE(Main, Top)% %Calculate%SCREENVISIBLE(Main, Width)% x %Calculate%SCREENVISIBLE(Main, Height)%

INTERNAL Left, Top, Width, Height
%Calculate%SCREENVISIBLE(Internal, Left)% %Calculate%SCREENVISIBLE(Internal, Top)% %Calculate%SCREENVISIBLE(Internal, Width)% x %Calculate%SCREENVISIBLE(Internal, Height)%

EXTERNAL Left, Top, Width, Height
%Calculate%SCREENVISIBLE(External,Left)% %Calculate%SCREENVISIBLE(External,Top)% %Calculate%SCREENVISIBLE(External,Width)% x %Calculate%SCREENVISIBLE(External, Height)%

SECOND Left, Top, Width, Height
%Calculate%SCREENVISIBLE(Second,Left)% %Calculate%SCREENVISIBLE(Second,Top)% %Calculate%SCREENVISIBLE(Second,Width)% x %Calculate%SCREENVISIBLE(Second, Height)%

THIRD Left, Top, Width, Height
%Calculate%SCREENVISIBLE(Third,Left)% %Calculate%SCREENVISIBLE(Third,Top)% %Calculate%SCREENVISIBLE(Third,Width)% x %Calculate%SCREENVISIBLE(Third, Height)%

GLOBAL and other variables
—————————————————
Screencount is >> %Calculate%SCREENCOUNT()%
Screenindex Internal is >> %Calculate%SCREENINDEX(Internal)%
Screenindex External is >> %Calculate%SCREENINDEX(External)%
Screenindex Second is >> %Calculate%SCREENINDEX(Second)%
Screenindex Third is >> %Calculate%SCREENINDEX(Third)%

You might want to ask for help on that issue. It might be a simple issue such as the timing of mouse clicks and drags.

It sounds like you would be happy with that method if it could be made to work reliably.

Do you mean System Settings->Displays loses the plot and rearranges your displays? Or that any positions you've set in KM are now on the wonk?

If it's the first -- macOS should remember arrangements when connecting to different setups, but you aren't doing that. You're pulling the plug on an existing setup. You could probably

  1. Sleep your laptop
  2. Turn off the HP
  3. Wake your laptop

...but if you don't want to waste time with that then take a look at DisplayPlacer, which will let you change arrangements programmatically on the fly.

If it's the latter...

KM's display positions are 1 through SCREENCOUNT(), left to right. You can't really save them, they just are. At your start, screen 1 is the small HP -- when you turn that off, screen 1 is the MacBook. But, your case, consider using "negative indices" because, since they go right-to-left, they don't change when you turn off your leftmost screen. -1 is always the Toshiba, -2 your MacBook.

I am publishing my set screen resolution macro very soon.
Here is correct arrangement of my three screens
Capto_Capture 2024-05-07_09-50-03_AM
then after turning monitors off etc and on I can get
Capto_Capture 2024-05-07_09-46-13_AM

or
Capto_Capture 2024-05-07_09-51-47_AM

I hope that makes it clearer.
I can live with it, but there does not seem to be anyway of making telling a screen its top left corner are co-ordinates say -500,-400 etc

I solve the screen index re-numbering problem by only using the keywords, Internal, External and Third.

This is an OS thing, not a KM thing. While the OS is good at remembering different display setups, like when moving between home and office, it copes less well when a setup changes because you've turned off (or on) a display.

The best way to solve this if you don't want to keep going through System Settings is DisplayPlacer (linked above) -- you could probably drive it via KM's "Display Layout Changed" trigger so you always had the correct layout, regardless.

IMO this is the best solution, because nothing would bug me more than having changing exit points when trying to mouse between displays!

From your initial description, that won't always work -- External would be either the small HP or the Toshiba, depending on whether the small HP is turned on or not. That you're also using vertical stacking may change that, but try referencing by negative index if you find reference by keyword to be flakey.

You can't (directly) with KM -- it uses coordinates reported by the system. Which is why you might be better off using relative rather than absolute coordinates. Moving a window to, say 1000, -1000 to put it on the top-right display in your first shown setup will break for the other two. But if you use coordinates relative to the top-left corner of the that display -- (SCREEN(-1,Left) + 100), (SCREEN(-1,Top) + 100) -- it doesn't matter how the OS rearranges things, the window will always be in the same place on that display (as long as the OS still thinks it is the rightmost, of course!).

None of this is to do with "resolution". If you are changing resolutions as well -- even more reason to take a look at DisplayPlacer!