Is It Possible to Center a Window Horizontally and Maintain Its Current Vertical Position?

I've looked at some other forum discussions re: centering windows, but haven't yet figured out the solution for this particular, desired action. The Center and Center at actions don't seem to provide the necessary parameters (but I'd be delighted to be wrong, if they do).

I want this command to work for windows of any size, and I don't want to specify a vertical position; I want that to remain unchanged (wherever that window happens to be located vertically).

Any suggestions would be appreciated.

Thanks.

1 Like

You can use the Manipulate a Window action to move the window to:

SCREEN(Front,MidX)-WINDOW(Width)/2
WINDOW(Top)

image

3 Likes

Thank you!! :blush:

Thanks for sharing this formula. I wasn't aware of this function and just tried to implement it into my Window moving Macros.

Unfortunately in my case it seems that this calculation takes more time than the resizement of the window. As follows the screenshot of my macro:

The second action (currently disabled for testing purposes) works with just one press of the hot key. If I use the first action like shown I have to press the hot key combination twice to move the window into the middle of the screen.

Is there something I can do against this behaviour?

Thanks in advance.

The calculation will take essentially zero time.

The Accessibility API occasionally bounces the window changes, and this can be exacerbated if any part of the window will move off the screen or by some software on your Mac if it turns on certain accessibility features.

Check the values of the two calculations:

SCREEN(Front,MidX)-WINDOW(Width)/2

and

SCREENVISIBLE(Main,MidX)*30%

and see what their difference is. Even a subtle difference may be responsible for the change in behaviour.

The speed of the calculation will not be.

You can try simply repeating the action, or repeating the action with a small pause between it.

Note that the second equation calculation does not really make sense:

SCREENVISIBLE(Main,MidX)*30%

This will be 30% of the distance between the desktop left edge and the middle of the main screen - if you have two monitors, this will not necessarily make any sense, although the desktop

If you want 15% across the main screen, you can use:

SCREENVISIBLE(Main,Left) + 15%*SCREENVISIBLE(Main,Width)

and Keyboard Maestro has a built in simplification for this which is:

SCREENVISIBLE(Main,Left,15%)

3 Likes

Thanks so much Peter!

It took me a while and some tests but at the end your hints helped me to find the reason for my issue.

Indeed this…

… is something I probably never will get. Since both are just calculations I probably will never understand why one would lead to a different behaviour than the other.

But anyway, first of all as I copied your example into my action I didn't recognize that there was the difference between "SCREEN" and "SCREENVISIBLE". Apologies for that.

The issue in my case was that the first calculation is - of course - based on the current window size.

This means if I want to position a window in the middle of the screen and resize it your formula just works if the window resizement happens before the positioning.

Thanks again!

1 Like

You don't actually need to -- you could include the resizing in the calculation. So something like (totally untested):

SCREENVISIBLE(Main,MidX) - (WINDOW(Width) * 70%) / 2

The best way is whichever one you'll understand when you revisit the macro in a year's time!

3 Likes

Thanks a lot @Nige_S!

I just checked and it behaves the same. I need more than one hotkey press to gain position and size.

If the window size doesn't change it works with one press.

I will just stuck with my two action version which works fine. :sunglasses:

Thanks again.

Hey Guys,

It looks to me like the most effective solution to this problem is to move the window first, so it has plenty of room to expand and then resize it and move it again.

The system can get picky about how it allows you to resize a window with automation, and that's why I always prefer to resize windows of scriptable apps with AppleScript using window-bounds. But that solution is not always available.

-Chris

Move and Resize Front Window v1.00.kmmacros (7.3 KB)
Keyboard Maestro Export

4 Likes

@ccstone's version, separating the move and resize, might sort things out for you. If not, the other way is to set a variable to your new, desired, window bounds and then repeat the move/resize until actual matches desired.

Chris's method is much shorter and easier :wink:

2 Likes

If I want to move the window on a horizontal pane, how can I do that?
On the y-coordinates, I can't replace WINDOW(Top) with 0, as that would move it to the top most point, touching the menubar. WINDOW(Height) seems to move it downwards.

In order to do that, (I think) you have to fetch the current window's top coordinate into a variable, and then use that variable in your Move Window action. The following example will move the front window ten pixels rightward:

1 Like

I'm sorry, I don't understand what you mean.

The action I showed will center the window horizontally, and leave its position unchanged vertically.

My apologies for not making it clear. @Airy gave me the solution. Thanks so much, Airy.

I have a window that sits anywhere in the screen and I wanted a macro that will nudge it to the left but maintain the same y-coordinate, thus on the same horizontal pane.

The use case is having two windows on top of each other and just needing to send one to the left, as a reference, while the eyes are looking at the other window. Most of the "Move" macro will move the window to the left and sometimes to the top left, bottom left, but never at the same "eye" level.

You are welcome. Peter used a different approach, that I didn't grasp at the time that he wrote it, but it will also work fine.

2 Likes

I have one macro that moves the window (on the same horizontal pane) to the left. I need another macro that moves to the right. Thanks to @Airy's approach, I learned that I can also use %WindowSize%Front%. Pasting it here in case it helps anyone looking for the same solution:

This will move the window to the right edge of the screen, leaving a gap of 50 pixel (I use Stage Manager, so 50 pixel is just wide enough to keep Stage Manager visible).

There are some situations in recent versions of macOS (probably when resizing a window, not just moving it) that you need to execute the Move Window action more than once (sometimes several times) before the window gets its final location. There is very annoying, and is a bug in macOS, but if that happens to you, you can use the following approach to fix it. In this approach, I created a variable called "LocalWindowNewPosition", and I place the new coordinates for the window into it. Then I create a loop and keep moving the window UNTIL it finally reaches the destination coordinates.

The code in the above example shows how to solve this problem, but this simplified code only deals with moving, not resizing. It would take a little more code to also deal with resizing, but this should give you the idea.

1 Like

Just so you're clear on this...

WINDOW(Top) gets the coordinate of the top of the frontmost window. So this bit

image|276x6450%

is quite literally "position the top of the window where the top of the window is".

That sounds a bit crazy because we more naturally think "don't change where the top of the window is", but it's that way because you have to provide "absolute" coordinates to that version of the "Manipulate a Window" action -- so anything "relative" you have to calculate on the fly.

@Airy's version is logically the same -- LocalWindowPosition.y gets the y coordinate from the variable LocalWindowPosition, and since you previously set that variable to be the front window's position that's the top of the window. But it needs an extra step because you first have to get the window's (x,y) and then get the y.

1 Like