Setting Window Sizes Precisely With a Script

You can use JXA in the Script Editor or Automator to set the location of a window to an exact location and size. It is easy to set up the one-line script and reuse it by simply changing the application name and size numbers. You can also create an Automator service to repeat a setting you use often.

Video Transcript
Let's say you want to control the windows on your Mac with precision. You want to set exactly where they are on the screen. Now there are a lot of great third party apps that you can install to allow you to control your windows. Putting them in the left half, the right half, putting them in certain spots. They have very, kind of, complex interfaces I think and unless you're doing it all the time it's probably not worth putting an entire other extension running on your Mac.

You can do it with just one line of code and get precision control. So I'm going to show you how to do it using the Script editor. Let's run Script Editor. I'm just going to use Spotlight to search for it so Command space and search for Script Editor. This is the editor where you could write AppleScript and also JavaScript or JXA.

So I'm going to create a new document here. The first thing I'm going to do, and this is very important, is I'm going to switch from AppleScript to JavaScript. Now you can do this in AppleScript. It's different coding. But I'm going to do it in JavaScript because you can do it in one line and I think JavaScript, JXA, is the future and AppleScript is kind of the old way of doing things.

So I'm going to paste in the text here and we can take a look at it. Basically it just has a bunch of parts and I love that in JXA you can do this in one line and AppleScript it would take several lines. So you've got Application, and then with parentheses and quotes the name of the application. Let's do Safari then let's dot windows and then bracket zero. In other words the first window. In coding you usually start counting at zero. So window number one is zero. So you take the first window or in this case the only window in Safari. Then you access a property called bounds. Bounds, of course, is just like it sounds. It's the rectangle that forms the window. Then here we have a bunch of different properties. We put those in quotes with a colon and then the value and then a comma between each one with curly brackets around it. We've got the x and the y, the left position and the top position, horizontal and vertical, and then we've got the width and the height.

So if we want to set the Safari window to be the upper left hand corner, 700 pixels wide and 400 high we use this exact piece of code. Now just this one line. All we need to do is execute it to run it. So I'm going to hit the Play button. Let me move it down a bit here and you can see the Safari window in the background. I'll hit Play and you can see it does exactly that. It moves the window to the upper left hand corner and sets its width to 700 and height to 400.

Now incidentally since Safari cannot go behind the Menu Bar there setting it to zero really didn't do anything. Setting the y coordinate to zero. For instance if I were to set it to 25 you can see it just moves down two pixels. That's because 23 is equivalent to zero and zero is going to push it down 23 pixels so it's not behind the Menu Bar. But the height stays the same. It's still 400 high. So using zero is just a quick way to getting it down. The corner is fine. If you want something more specific like you want it to be ten pixels below the Menu Bar then you would have to do 33. You can do trial and error to figure out other similar things.

You can do the same thing in Automator. Command space here. Run Automator and I'm going to create in Automator a new Service which will be handy. I'm going to say it takes no input and runs only in Safari. Then I'm going to search for the run JavaScript action. Put that there. Put the same line of code there. So this is exactly what I had in the Script Editor. I can test it out. So with Safari here I can move this. I can run this. In Automator you can see it snaps it up there to the top left. Then I can Save it as To Upper Left. Save. Now I can find it in the Safari Services menu. So say I change Safari to be some other size. I go to Safari Services. You can see To Upper Left and it snaps it in place there.

So a handy little thing. Of course you can go and expand that if you're experienced in using JXA to pull the application from whatever application is running or having a variety of things. You can even have multiple lines here. So you could have a script that sets the Safari window to one location and maybe a TextEdit window to another location. Things like that and run these. A lot of cool things that you can do with these if you want this kind of precision in handling your windows. For me a big thing would be to maybe make it 1280 x 720. Therefore when I shoot videos that show a window ,like Safari window, they can be exact size to match a video that I create.

Here is an example of the JXA script I am using in the video:
Application("Safari").windows[0].bounds = {"x":0, "y":0, "width":1280, "height":697}

Comments: 19 Responses to “Setting Window Sizes Precisely With a Script”

    Mark V.
    1/30/18 @ 2:00 pm

    Hello Gary. Informative video. Two questions. First I tried to build an automator service for Firefox and it would not show up under services when I used in “Firefox” or in “Any Application”.

    Second, where do i find identifiers for the different windows? I was trying to put apps on different desktops and then also on my main laptop screen. Now I’m using the monitor attached to the laptop as “.windows[0]”.

    1/30/18 @ 2:03 pm

    Mark: Sometimes those services can be finicky. Try quitting Firefox and Automator. Then launch just Automator. Create the service from scratch. Save it. Then launch Firefox and see if it is there.
    The windows for an app are just numbered. I’m not sure you can get an “identifier” that is reliable.

    Mark V.
    1/30/18 @ 2:15 pm

    Thanks for the response on the first part. As for the second, I guess I was trying to put apps on other desktops. I tried 1,2&3 but none worked, I tried -1 as well. Does this

    Application(“Safari”).windows[0].bounds

    Always have to be 0?

    1/30/18 @ 2:17 pm

    Mark: windows[0] means the first window of the application. For instance, if Safari had two windows open, one would be windows[0] and the other windows[1]. It doesn’t have to do with screens. Not sure if you can set the bounds to another screen. There is probably another property, separate from bounds, that represents the screen. I don’t know what that would be offhand.

    Mark V.
    1/30/18 @ 3:02 pm

    Ok, I’m with you now! Thanks!

    Mark Scola
    2/1/18 @ 9:54 am

    Hey Gary, I like this idea. How’s about posting the text code?

    2/1/18 @ 9:56 am

    Mark: I just put an example under the video above.

    Mark Scola
    2/1/18 @ 10:47 am

    Thanks Gary, it works perfectly. Nice trick to know!

    nick
    2/1/18 @ 1:27 pm

    Always amazed of all the little utilities in the Mac OS. Thanks Gary, I’m forever resizing windows on the desktop and this is a clever solution. Question: to make the service available in other apps would I just add more script lines below the Safari one, following the same syntax?

    2/1/18 @ 1:35 pm

    nick: No, it would get a lot more complex. If you had two lines, one for Safari and one for Mail, then every time you ran the script it would resize the first window in both apps. You’ll need to add more code to figure out the current app and use that instead. It will take some AppleScript/JXA know-how.

    Actually, if you just replaced Application(“Safari”) with Application.currentApplication() it may do what you want.

    Lali Raj
    2/1/18 @ 2:05 pm

    Thanks Gary, it will really help instead of resizing an apps screen. Once again thanks for the tip

    Lali Raj
    2/1/18 @ 2:08 pm

    Gary is there anyway one can create a similar script for finder window?

    2/1/18 @ 2:12 pm

    Lali: Just change the application name to “Finder” instead.

    Brett
    2/1/18 @ 2:24 pm

    Thanks Gary, appreciate this post. This works great with two application windows side by side, triggered by a services keyboard short-cut. Thanks again!

    Lali Raj
    2/1/18 @ 2:34 pm

    Gary I setup the JXA script for TextEditor app, it worked when I tested it but when I restarted the computer it did not work. Why?

    2/1/18 @ 2:35 pm

    Lali: I don’t know. Try building it again. Test, experiment, explore, etc.

    Cory
    2/2/18 @ 7:03 pm

    Thanks Gary! I really like this script.
    Someone asked how to do this with multiple monitors. add “-” before the position of the window. Basically the second display is negative position.
    Here is what I used to equally size 4 windows on 2 monitors:
    {“x”:0, “y”:0, “width”:960, “height”:1200}
    {“x”:960, “y”:0, “width”:960, “height”:1200}
    {“x”:-960, “y”:0, “width”:960, “height”:1200}
    {“x”:-1920, “y”:0, “width”:960, “height”:1200}

    Cory
    2/2/18 @ 7:06 pm

    Also Gary, How can I use this script to resize windows of any open application. Say I want safari, chrome and firefox all open and resize them equally.
    I have tried:
    Application(*)
    but I get errors.
    Thank you!!

    2/2/18 @ 9:17 pm

    Cory: You can’t use * as a wildcard or anything like that. You’d need to do a line for each app and window, or just change the app name and values and run it again and again.

Comments Closed.