8

I have experimented with absolutely every possible scripting option I can find on the web, and no matter what I do I cannot move a FaceTime window to my secondary display.

This works...

tell application "System Events" to tell process "FaceTime"
  tell application "FaceTime" to activate
  tell front window to set position to {3600, 500}
end tell

but with one fatal flaw that it always stops dead in its tracks, at the right edge of display #1 (the left display).

If I set the X coordinate to anything less than 2560 (my width on both screens) then it works perfectly, but any attempt to move it further to the right, and thus onto display #2, will not work.

I don't know if it's related, but my primary display is an external Dell, and my secondary display is the built-in display of the 27" iMac. Dell on the left, iMac on the right.

Interestingly however, if I manually drag the window onto display #2 and run the same script above, then it positions correctly onto display #2. It seems that the numbers are relative to whatever display the window is CURRENTLY on. How can I get it to absolutely position the window onto display #2?

3
  • I'm trying to save you here... bettertouchtool for window management.. don't use applescript unless necessary.
    – Jahhein
    Apr 14, 2021 at 18:20
  • 1
    Thanks for the info, but this need was from 2012 and is no longer.
    – JVC
    Apr 14, 2021 at 23:48
  • Then I'll follow up with another optional app; Keyboard Maestro. I'm not affiliated, I just love both apps!
    – Jahhein
    Apr 15, 2021 at 20:54

5 Answers 5

2

It looks like Apple have set the window to be aware of what Display it should be on and not extend outside of thats Displays bounds when launching.

A side effect of this is the App will do the same thing with the calls from the applescript.

You can see this if you straddle the window across both Displays. Then quit and relaunch the app.

The window will open on only one of the displays and not be straddled.

If you did the same for say Safari. The window you had straddling would still be straddling.

I think you are out of luck doing it in any way useful.

The only way I got it to do it was to get the window and display details from the plist file '~/Library/Preferences/com.apple.FaceTime' while the window was on the second display.

 (* read plist file *)
    do shell script "/usr/bin/defaults read ~/Library/Preferences/com.apple.FaceTime NSWindow\\ Frame\\ FaceTimeWindowFrame"

Then when the app was on the first display.

Run a script which quit the app, rewrites the 'NSWindow Frame FaceTimeWindowFrame' entry in the plist with the info for the position and display I had from earlier.

Activate the app again, which would open on the second display. And then move it with the normal applescript code.

tell application "FaceTime" to quit
(do shell script "/usr/bin/defaults write ~/Library/Preferences/com.apple.FaceTime NSWindow\\ Frame\\ FaceTimeWindowFrame" & (" '2562 853 638 585 2560 240 1920 1200'") as string) --set to somewhere on my second screen

delay 1
tell application "System Events"

    tell application "FaceTime" to activate

    delay 4
    set position of window "FaceTime" of application process "FaceTime" to {3269, 315}

    end tell

But like I said not very useful. :-(

1
  • WOW... that is some brute force all right. Thank you for the effort, but you're right... not terribly useful. What a shocking bummer! =(
    – JVC
    Oct 7, 2012 at 16:37
2

While this does not directly answer the question of using applescript, it may be a valid answer for the actual issue of moving windows.

You can use a small third party application like Slate.

With minor configuration it can be set to move the window by title when Slate launches, when a key is pressed, or when a condition is met.

It can also be configured to move any window to a specific position when a key is pressed or a condition is met.

Slate may fit the request because it's footprint is extremely small, and it does not require administration privileges.

A good introduction:

http://mauriciogardini.com/post/43348489262/slate-a-mac-os-x-window-manager-for-power-users

1
  • Very cool alternative, thanks! I wasn't married to using AppleScript, it was just the only approach I could think of. I'll give this one a shot the next time I want to do this.
    – JVC
    Oct 8, 2013 at 22:21
2

There is now (from Catalina? onwards) a menu command in the Window menu to move the current window to another display.

So you could do it with GUI scripting.

enter image description here

2
  • Thanks for the info, but this need was from 2012 and is no longer.
    – JVC
    Apr 14, 2021 at 23:48
  • how would you do it with GUI scripting. And do you know of any way to move it to 1) the active screen? 2) where the mouse it? 3) Where the cursor is? Nov 23, 2021 at 12:33
1

Below is my solution. It resizes and positions the frontmost window proportionally on the second screen. It's a few lines of code because it also takes into account all the various options how you can position your monitors in system preferences and such…

# http://superuser.com/questions/331313/how-to-automagically-move-windows-between-monitors-with-one-keystroke
# https://stackoverflow.com/questions/6565703/math-algorithm-fit-image-to-screen-retain-aspect-ratio
# https://forum.latenightsw.com/t/get-sizes-of-monitor-s-via-applescript/1351/10

---
use framework "Foundation"
use framework "AppKit"
use scripting additions

set allFrames to (current application's NSScreen's screens()'s valueForKey:"frame") as list
try
    set _mon1 to item 2 of item 1 of allFrames
    set _mon2 to item 2 of item 2 of allFrames
    
    set _mon1Width to item 1 of _mon1
    set _mon1Hight to item 2 of _mon1
    set _mon1Size to _mon1Width + _mon1Hight
    
    
    set _mon2Width to item 1 of _mon2
    set _mon2Hight to item 2 of _mon2
    set _mon2Size to _mon2Width + _mon2Hight
    
    set _screenWar to (_mon2Width / _mon1Width) # width adaption ratio of screen 1 & 2
    set _screenHar to (_mon2Hight / _mon1Hight) #  hight adaption ratio of screen 1 & 2 
    
    tell current application to set _hightoffset to do shell script "/usr/libexec/PlistBuddy -c 'Print :DisplayAnyUserSets:Configs:0:0:CurrentInfo:OriginY ' /Library/Preferences/com.apple.windowserver.displays.plist"
    set _hightoffset to _hightoffset as feet as number
    
    tell current application to set _widthoffset to do shell script "/usr/libexec/PlistBuddy -c 'Print :DisplayAnyUserSets:Configs:0:0:CurrentInfo:OriginX ' /Library/Preferences/com.apple.windowserver.displays.plist"
    set _widthoffset to _widthoffset as feet as number
    
    # detect position of the second screen in relation to the main screen
    if _mon1Width = _widthoffset then
        # say "Rechts"
        set _right to true
    else if _mon1Hight = _hightoffset then
        set _right to false
        set _bottom to true
    else if _mon2Width = -_widthoffset then
        set _right to false
        set _bottom to false
        set _left to true
    else if _mon2Hight = -_hightoffset then
        set _right to false
        set _bottom to false
        set _left to false
        set _top to true
    end if
end try

try
    tell application "System Events"
        tell (first process whose frontmost is true)
            set _windowPos to position of window 1
            set x to item 1 of _windowPos # x = position width 
            set y to item 2 of _windowPos # y = position hight 
            
            set _windowSize to size of window 1
            set _windowWidth to (item 1 of _windowSize)
            set _windowHight to (item 2 of _windowSize)
            
            
            # set current location (which monitor) of the frontmost window and new window size and postion 
            if _right is true then
                if x < _mon1Width then
                    set _newSize to {_windowWidth * _screenWar, _windowHight * _screenHar}
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + (_hightoffset + 25)} # menubar = 25 pixel
                    set _winLocation to "mon1"
                else
                    set _newPosition to {(x - _widthoffset) / _screenWar, ((y - (_hightoffset + 25)) / _screenHar) + 25}
                    set _newSize to {_windowWidth / _screenWar, _windowHight / _screenHar}
                    set _winLocation to "mon2"
                end if
                
            else if _bottom is true then
                if y < _mon1Hight then
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + (_hightoffset + 25)}
                    set _newSize to {_windowWidth * _screenWar, _windowHight * _screenHar}
                    set _winLocation to "mon1"
                else
                    set _newPosition to {(x - _widthoffset) / _screenWar, ((y - (_hightoffset + 25)) / _screenHar) + 25}
                    set _newSize to {_windowWidth / _screenWar, _windowHight / _screenHar}
                    set _winLocation to "mon2"
                end if
            else if _left is true then
                if x > -1 then
                    set _newSize to {_windowWidth * _screenWar, _windowHight * _screenHar}
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + (_hightoffset + 25)}
                    set _winLocation to "mon1"
                else
                    set _newPosition to {(x - _widthoffset) / _screenWar, ((y - (_hightoffset + 25)) / _screenHar) + 25}
                    set _newSize to {_windowWidth / _screenWar, _windowHight / _screenHar}
                    set _winLocation to "mon2"
                end if
            else if _top is true then
                if y < 25 then
                    set _newPosition to {(x - _widthoffset) / _screenWar, (y + (-_hightoffset - 25)) / _screenHar + 25}
                    set _newSize to {_windowWidth / _screenWar, (_windowHight + 25) / _screenHar - 25}
                    set _winLocation to "mon2"
                else
                    set _newSize to {_windowWidth * _screenWar, (_windowHight + 25) * _screenHar - 25}
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + _hightoffset + 25}
                    set _winLocation to "mon1"
                end if
            end if
            
            # checking for window loaction and whether the monitor it is located on is bigger or smaller than the other one 
            if _winLocation is "mon1" then
                if _mon1Size > _mon2Size then
                    set size of window 1 to _newSize
                    set position of window 1 to _newPosition
                else
                    set position of window 1 to _newPosition
                    set size of window 1 to _newSize
                end if
                
            else
                if _mon2Size > _mon1Size then
                    set size of window 1 to _newSize
                    set position of window 1 to _newPosition
                else
                    set position of window 1 to _newPosition
                    set size of window 1 to _newSize
                end if
            end if
            
        end tell
    end tell
end try
2
  • Thanks for the info, but this need was from 2012 and is no longer.
    – JVC
    Apr 14, 2021 at 23:48
  • 2
    @JVC That doesn't mean others aren't looking at this question for answers! :)
    – Tim Malone
    Apr 22, 2022 at 5:11
1

My solution is to use both AppleScipt via Shortcuts and amethyst

and here is the script


# key codes:
# 13 w
# 14 e
on run {input, parameters}
    tell application "System Events" to key code 13 using {control down, option down, shift down}
    return input
end run
# corresponds to `Throw focused window to screen 1`

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .