Resize window on drag to 2nd screen

I searched for this and couldn't find a previous post, which seems unlikely. Please point me to another thread if there is one.

I have a dual monitor rig, with the left monitor in landscape and my right monitor portrait. When I drag a window from one screen to the other, I'd like it to resize to 75% of the width of the current screen.

How would you trigger that?

Probably the best way to "trigger" it is use something like the following:

In this example I simply play a sound when the window moves. It may be possible to use this to achieve what you want. But I need to figure out how to detect which display the window's location is on.

One of the problems with your question is that a window can be placed across two screens at once. I don't have any idea what you would want in that case.

I think I'm getting close to a solution. But another problem I have is that window titles are not unique. You could have two windows with the same title, which macOS does not prevent from occurring. However that's an unlikely situation for most people, so maybe you won't mind an imperfect solution.

Okay, let me outline my solution with some screenshots. I'm unable to test my solution until I connect another monitor. If you want, you can create this macro yourself and try to test/debug it. Normally I do all the testing and debugging, but without a second monitor I can't do that.

The first thing is to trigger the macro whenever a window moves. You do that like this:

This will trigger the macro dozens of times while you are moving it, so the first trick is to add a semaphore to the top of the macro with a short timeout, probably a third of a second. Technically this does NOT get the last known position of the window, instead it gets roughly the Nth last position (eg, third last), but that's good enough because the window moves so often and triggers this macro so often that the third last position will be on the destination window about 99% of the time. I admit this is a bit of a hack, but I think it will work fine.

The next trick is to pause the macro, which locks the semaphore for a short period of time, like this. I'm not 100% certain if this is necessary, but it helped me debug it. Once the macro works, I'll test removing this action.

image

For the next trick we will refer to a dictionary that we will store the last known display number of any window of a particular name. The dictionary can be called anything, but I'm calling it EachWindowScreen, because it contains the screen index number of each window, using the window name as the key. Bear in mind that if your window names change, it will "forget" the screen index for that window. I don't know if your window names are steady or volatile because you didn't say which apps you are doing this with.

image

In the above action, the first thing this macro does is test if the "EachWindowScreen" dictionary is storing a "last known screen number" for the current window. If it does not, it saves the current screen number for the current window using the name of the current window as the key.

But if it DOES have a memory of the "last known screen number" then it check if the current screen number for the front window is different from the "last known screen number" for the window. If the values are the same, it does nothing. (Because it can't detect a change until it has detected the window at least once.) But if the values are different, it uses the KM "Move and Resize Window" action to resize the window to 75%. I coloured that action red because I stopped at that point, since I don't currently have a second monitor to test. So that final action may need some modification before it works.

So that's it... under ten actions. There might be some people on this forum who can spot better ways to tackle this problem. I'm open to suggestion. Since you have two displays, you could create this macro, see if you can get it to work, and come back here for help if it doesn't work.

I don't think the following is necessarily a better approach, but it's a different approach that gets to the same end result, and does so in a one-action macro. In order to do that, though, I chose to ignore the "drag" portion of the request. As @Airy has shown, tracking drags is…well, it's a drag.

To avoid this problem, my solution moves the frontmost window to the current mouse location, and sizes it to 75% of that display's available width and height. Here's the macro:

Download Macro(s): Move and resize to other display.kmmacros (2.1 KB)

Macro screenshot

To use, position the mouse where you want the window, then press Shift-Control-M.

The key to this is the SCREEN(Back... function, as the back screen is defined as the leftmost screen that is not the frontmost screen. And in a two-display setup, that will always be the display the frontmost window is not on.

So the macro simply moves the frontmost window to the non-active display, and sets its size to 75% of the width and height of that display.

Upsides of this solution: Incredibly simple macro, no window dragging required.

Downsides of this solution: You can only move the frontmost window. You can't do it via dragging. It requires a keyboard shortcut (or you could put it in the KM menu bar item). And if you run it when the mouse is on the same display as the window to be moved, the window will move and resize to 75% of the other display's screen size :). (In theory, you could check the mouse location compared to the location of each display, and cancel the macro if the mouse is on the current display…but I leave that as an exercise to others.)

Anyway, just a different approach to solving your problem; I have no idea if this is a method you'd like to use or not, but thought I'd offer it up as an alternative.

-rob.

1 Like

I like your idea. It is a good example of thinking outside the box.

I also like my idea, even though, embarrassingly, my code wasn't completed.

I'd offer a third way, using hot keys to send a window from one display to the other, but it suffers from two problems:

  1. It's not what you asked for :wink:
  2. You need to decide how you like the window positioned on the other display -- top-left corner in the same relative poistion? Window centre in the same relative position? Always to the same horizontal, but vertically centred on the new screen?

So here's what I think you want, drag-wise. The trick is that the "Window Frame Change" trigger fires almost as soon as you start to drag the window -- that lets us grab the current screen index. (It keeps firing as you drag, so there's a semaphore lock so we don't leave unnecessary instances running!)

If we then wait until the mouse button is released -- the end of the drag -- we can check if screen index has changed and, if so, resize the window. I've kept the window height the same, but you could easily change that as well.

We check for the screen index change so that you still manually resize a window that you keep on the same screen :wink:

Not fully tested, since my displays are the same size, but seems to work as advertised -- shout if there are problems.

Window resize on drag to other display.kmmacros (5.3 KB)

Image

Thanks @Airy and @griffman for taking the time to work this out.

@Nige_S thanks - this did the trick!

Cheers!