Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening multiple windows with Applescript

I am trying to write an Applescript to open three VLC windows in different screen positions. The script opens three instances of VLC but has them one on top of the other (using the position for window 1). Help with the code appreciated:

do shell script "open -n /Applications/Video/VLC.app"
tell application "System Events"
    activate
    set bounds of first window of application "VLC" to {13, 36, 790, 519}
end tell

do shell script "open -n /Applications/Video/VLC.app"
tell application "System Events"
    activate
    set bounds of second window of application "VLC" to {13, 544, 790, 1027}
end tell

do shell script "open -n /Applications/Video/VLC.app"
tell application "System Events"
    activate
    set bounds of third window of application "VLC" to {13, 1043, 790, 1526}
end tell
like image 670
Jeff Avatar asked Aug 23 '26 09:08

Jeff


1 Answers

@khagler's comment provides the right pointer: the VLC instances must be distinguished by their PIDs (process IDs; called unix id in AppleScript) in the System Events context.

The code below should do what you want, arrived at after much toil and trouble -- par for the [AppleScript obstacle] course. One obstacle was that the VLC instances' main windows do not get created right away.

The comments provide more details.

Note that because user-interface elements are programmatically manipulated, the application running your script must be granted assistive access for security reasons.

Note that I'm starting the instances with do shell script "open -na VLC.app", relying on the location of the app being known to Launch services (should that not work for some reason, revert to your method of specifying the full path).

# Specify the desired window bounds.
# !! In the "System Events" context, windows do not 
# !! have `bounds` properties, but separate `position` and
# !! `size` properties.
set WIN_POSITIONS to {{13, 36}, {13, 544}, {13, 1043}}
set WIN_SIZES to {{790, 519}, {790, 519}, {790, 519}}

# Launch the VLC instances.
repeat with i from 1 to count of WIN_POSITIONS
    do shell script "open -na VLC.app"
end repeat

# Note:
# Instance-specific manipulation must
# be performed in the "System Events" context, because
# we must distinguish the VLC instances by their
# PIDs (process IDs; called `unix id` in AppleScript).
tell application "System Events"

    # Get the PIDs (process IDs) of all VLC instances.
    set vlcPids to get the unix id of every process whose name is "VLC"

    # Loop over all instance PIDs.
    # !! It is imperative to *continue* to use object specifiers
    # !! with *filters based on the PID* so as to ensure that the
    # !! individual instances are targeted.
    # !! Attempting to store references to these instances in
    # !! variables fails subtly, as evidenced by the "Events"
    # !! tab in AppleScript editor later showing the non-specific
    # !! process "VLC" of application "System Events" specifiers.
    set winNdx to 1
    repeat with vlcPid in vlcPids

        # WAIT for each instance to create its main window, wich
        # sadly, is not available right away.
        # Once created, position it.
        set haveWin to false
        tell (first process whose unix id is vlcPid)
            repeat with i from 1 to 25 # times out after 25 * .2 == 5 secs.
                if (count of windows of it) > 0 then
                    set haveWin to true
                    tell front window of it
                        # !! In the "System Events" context, windows do not 
                        # !! have `bounds` properties, but separate `position` and
                        # !! `size` properties.
                        set position to item winNdx of WIN_POSITIONS
                        set size to item winNdx of WIN_SIZES
                    end tell
                    exit repeat
                end if
                delay 0.2 # no window yet; sleep some and try again
            end repeat
        end tell
        if not haveWin then error "VLC instance " & vlcPid & " unexpectedly did not create a window within the timeout period."

        set winNdx to winNdx + 1
    end repeat

end tell

How to make this work with Finder:

Targeting Finder changes the approach for two reasons:

  • there's only one Finder instance.
  • you cannot open multiple windows with open -na Finder.app; thankfully, this answer shows how to do it (see the comments there for quirks).

Note that the following blindly opens additional Finder windows.

set WIN_POSITIONS to {{13, 36}, {13, 544}, {13, 1043}}
set WIN_SIZES to {{790, 519}, {790, 519}, {790, 519}}

# Sample target locations for the Finder windows.
# Note the use of the "System Events" context to faciliate use of
# POSIX-style *input* paths; note, however, that the paths are
# *stored* as HFS paths so that Finder accepts them.
tell application "System Events"
    set WIN_TARGETS to {¬
        path of desktop folder, ¬
        path of folder "~/Downloads", ¬
        path of folder "/Library/Audio"}
end tell

set winCount to count of WIN_POSITIONS

# Launch the Finder windows.
tell application "Finder"
    # Create the windows in reverse orders.
    repeat with i from winCount to 1 by -1
        set newWin to make new Finder window
        set target of newWin to item i of WIN_TARGETS
    end repeat
end tell

tell application "System Events"

    set i to 1
    repeat with i from 1 to winCount

        tell window i of application process "Finder"
            # !! In the "System Events" context, windows do not 
            # !! have `bounds` properties, but separate `position` and
            # !! `size` properties.
            set position to item i of WIN_POSITIONS
            set size to item i of WIN_SIZES
        end tell

    end repeat

end tell
like image 75
mklement0 Avatar answered Aug 26 '26 22:08

mklement0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!