AppleScript:使用Lion Fullscreen

时间:2011-11-21 16:59:33

标签: applescript osx-lion fullscreen

Apple官方文档中似乎没有任何相关信息。如何通过AppleScript使应用程序使用Lion的全新全屏功能?

4 个答案:

答案 0 :(得分:12)

不仅没有记录,而且行为是彻头彻尾的拜占庭。 以下内容适用于 Mountain Lion (截至10.8.1),但我怀疑它同样适用于Lion。

缺点:

如果它是最前面应用程序的活动窗口,则只能检查全屏窗口的状态。因此,您必须先激活您要检查的任何窗口。

如果该窗口确实当前处于全屏模式但不是活动模式,则激活将花费一些时间 - 转换动画的持续时间 - 仅之后,可以通过编程方式访问该窗口。

只要您只对活动(最前面)应用程序的活动(前)窗口感兴趣,一切都很花哨;否则,你会感到痛苦。

以下是执行以下操作的脚本:

  • 指示活动(最前面)应用程序中的活动窗口是否处于全屏模式。
  • 切换活动应用程序中活动窗口的全屏状态。
  • 指明可指定的应用程序是否具有任何全屏窗口。
  • 可以定位可指定应用程序的通用全屏管理脚本;这比应该的要复杂得多。

最后,最后还有一些额外的背景信息 - 非常有趣。

请注意,以下脚本需要通过System Preferences>启用辅助设备的访问权限Accessibility,或通过以下命令:tell application "System Events" to set UI elements enabled to true;需要管理权限。

指示活动(最前面)应用程序中的活动窗口是否处于全屏模式

(* 
  Indicates if the active window of the active application is currently in fullscreen mode.
  Fails silently in case of error and returns false.
*)
on isFullScreen()
    tell application "System Events"
        try
            tell front window of (first process whose frontmost is true)
                return get value of attribute "AXFullScreen"
            end tell
        end try
    end tell
    return false
end isFullScreen

切换活动应用程序中活动窗口的全屏状态

(* 
  Toggles fullscreen status of the active window of the active application.
  Return value indicates if the window is in fullscreen mode *after* toggling.
  Fails silently in case of error, e.g., if the active application doesn't support fullscreen mode, and returns false.
*)
on toggleFullScreen()
    set isFullScreenAfter to false
    tell application "System Events"
        try
            tell front window of (first process whose frontmost is true)
                set isFullScreen to get value of attribute "AXFullScreen"
                set isFullScreenAfter to not isFullScreen
                set value of attribute "AXFullScreen" to isFullScreenAfter
            end tell
        end try
    end tell
    return isFullScreenAfter
end toggleFullScreen

指示可指定的应用程序是否具有任何全屏窗口

**注意:此子例程仅适用于支持AppleScript的应用程序。**

(*
 Determine if the specified, *AppleScript-enabled* application currently has windows in fullscreen mode or not.
 Note: Assumes that the application name is the same as the process name.
*)
on hasFullScreenWindows(appName)
    -- We compare the count of visible application windows to the count of the application *process'* windows.
    -- Since process windows either do not include the fullscreen windows or, if a fullscreen window
    -- is active, only report that one window, a discrepancy tells us that there must be at least one fullscreen window.
    set countAllWindows to count (windows of application appName whose visible is true)
    tell application "System Events" to set countProcessWindows to count windows of process appName
    if countAllWindows is not countProcessWindows then
        set hasAny to true
    else
        set hasAny to false
        -- The app-window count equals the process-window count.
        -- We must investigate one additional case: the app may be currently frontmost and could have
        -- a single window that is in fullscreen mode.
        tell application "System Events"
            set activeProcName to name of first process whose frontmost is true
            if activeProcName is appName then
                tell process appName
                    tell front window
                        set hasAny to get value of attribute "AXFullScreen"
                    end tell
                end tell
            end if
        end tell
    end if
    return hasAny
end hasFullScreenWindows

可以定位可指定应用程序的通用全屏管理脚本

**注意:此子例程仅适用于支持AppleScript的应用程序。**

(*
Sets the fullscreen status for either the front window or all windows of the specified, *AppleScript-enabled* application.
The 2nd parameter can take the following values:
 0 … turn fullscreen OFF
 1 … turn fullscreen ON
 2 … toggle fullscreen
The 3rd parameter is used to specify whether *all* windows should be targeted.

Example:
  my setFullScreen("Safari", 2, false) toggles fullscreen status of Safari's front window. 

NOTE:
    - ONLY works with AppleScript-enabled applications.
    - The targeted application is also activated (also required for technical reasons).
    - If you target *all* windows of an application, this subroutine will activate them one by one, which
      is required for technical reasons, unfortunately.
      This means: Whenever you target *all* windows, expect a lot of visual activity, even when 
      the fullscreen status needs no changing; activity is prolonged when fullscreen transitions
      are involved.
     - If the target application has a mix of fullscreen and non-fullscreen windows and the application
      is not currently frontmost, the OS considers the first *non*-fullscreen window to
      be the front one, even if a fullscreen window was active when the application was
      last frontmost.
*)
on setFullScreen(appName, zeroForOffOneForOnTwoForToggle, allWindows)

    # Get window list and count.
    tell application appName
        set wapp_list to windows whose visible is true
        set wcount to count of wapp_list
        ## set wapp_names to name of windows whose visible is true
        ## log wapp_names
    end tell

    set MAX_TRIES to 20 # Max. number of attempts to obtain the relevant process window.

    set toggle to zeroForOffOneForOnTwoForToggle is 2
    set turnOn to false
    if not toggle then set turnOn to zeroForOffOneForOnTwoForToggle is 1

    if allWindows and wcount > 1 then -- Target *all* the application's windows.
        tell application "System Events"
            tell process appName
                set indexOfTrueFrontWin to -1
                set wproc_target to missing value
                set wproc_targetName to missing value
                -- Loop over application windows:
                -- Note that we have 2 extra iterations:
                --  Index 0 to determine the index of the true front window, and count + 1 to process the true front window last.
                repeat with i from 0 to wcount + 1
                    ## log "iteration " & i
                    if i ≠ 0 and i = indexOfTrueFrontWin then
                        ## log "ignoring true front win for now: " & i
                    else
                        set ok to false
                        if i ≠ 0 then
                            set wapp_index to i
                            if i = wcount + 1 then set wapp_index to indexOfTrueFrontWin
                            set wapp_target to get item wapp_index of wapp_list
                            set wapp_targetName to get name of wapp_target -- Note: We get the name up front, as accessing the property below sometimes fails.
                        end if
                        repeat with attempt from 1 to MAX_TRIES
                            ## log "looking for #" & i & ": [" & wapp_targetName & "] (" & id of wapp_target & ")"
                            # NOTE: We MUST activate the application and the specific window in case that window is in fullscreen mode.
                            #        Bizzarrely, without activating both, we would not gain access to that active window's *process* window,
                            #        which we need to examine and change fullscreen status.
                            if i ≠ 0 then
                                ## log "making front window: " & wapp_targetName
                                set index of wapp_target to 1 -- Make the window the front (active) one; we try this *repeatedly*, as it can get ignored if a switch from a previous window hasn't completed yet.
                            end if
                            set frontmost to true -- Activate the application; we also do this repeatedly in the interest of robustness.
                            delay 0.2 -- Note: Only when the window at hand is currently in fullscreen mode are several iterations needed - presumably, because switching to that window's space takes time.
                            try
                                -- Obtain the same window as a *process* window.
                                -- Note: This can fail before switching to a fullscreen window is complete.
                                set wproc_current to front window
                                -- See if the desired process window is now active.
                                -- Note that at this point a previous, fullscreen window may still be reported as the active one, so we must
                                -- test whether the process window just obtained it is the desired one. 
                                -- We test by *name* (window title), as that is the only property that the *application*
                                -- window class and the *process* window class (directly) share; sadly, only application windows
                                -- have an 'id' property.
                                -- (There is potential for making this more robust, though, by also comparing window sizes.)
                                if i = 0 then
                                    -- We determine the index of the *actual* front window, so we can process it *last*
                                    -- so we return to the same window that was originally active; with fullscreen windows
                                    -- involved, sadly, `front window` is NOT always the true front window. 
                                    set indexOfTrueFrontWin to 1
                                    repeat with ndx from 1 to wcount
                                        if name of (item ndx of wapp_list) is name of wproc_current then
                                            set indexOfTrueFrontWin to ndx
                                            exit repeat
                                        end if
                                    end repeat
                                    ## log "true front index: " & indexOfTrueFrontWin
                                    set ok to true
                                    exit repeat
                                else
                                    if (name of wproc_current) is wapp_targetName then
                                        ## log "processing: [" & name of wproc_current & "]"
                                        tell wproc_current
                                            set isFullScreen to get value of attribute "AXFullScreen"
                                            if toggle then set turnOn to not isFullScreen
                                            if isFullScreen is not turnOn then
                                                ## log "setting fullscreen to: " & turnOn
                                                set value of attribute "AXFullScreen" to turnOn
                                                delay 0.3 -- For good measure; it seems turning fullscreen *on* sometimes fails (you'll hear a pop sound).
                                            else
                                                ## log "no change needed"
                                            end if
                                        end tell
                                        set ok to true
                                        exit repeat
                                    else
                                        ## log "no match; waiting for '" & wapp_targetName & "', actual: '" & name of wproc_current & "'"
                                    end if
                                end if
                            end try
                        end repeat
                        if not ok then error "Obtaining process window '" & wapp_targetName & "' of application " & appName & " timed out."
                    end if
                end repeat
            end tell
        end tell
    else if wcount > 0 then -- Target *current* window only (if there is one).
        tell application "System Events"
            tell process appName
                # NOTE: We MUST activate the application in case its active window is in fullscreen mode.
                #       Bizzarrely, without activating, we would not gain access to that active window's *process* window.
                set frontmost to true
                set ok to false
                repeat with attempt from 1 to MAX_TRIES
                    delay 0.2 -- Note: Only when the active window is currently in fullscreen mode are several iterations needed - presumably, because switching to that window's space takes time.
                    try
                        -- Obtain the same window as a *process* window, as only a process window allows us to examine or
                        -- change fullscreen status.
                        tell front window -- Note: This can fail before switching to a fullscreen space is complete.
                            set isFullScreen to get value of attribute "AXFullScreen"
                            if toggle then set turnOn to not isFullScreen
                            if isFullScreen is not turnOn then
                                set value of attribute "AXFullScreen" to turnOn
                            end if
                        end tell
                        set ok to true
                        exit repeat
                    end try
                end repeat
                if not ok then error "Obtaining active process window of application" & appName & " timed out."
            end tell
        end tell
    end if

end setFullScreen

更多背景资料:

  • 应用程序窗口集合 - 在tell application ...块的上下文中可访问的窗口集合 - 始终报告窗口的总数,无论它们是否处于全屏模式。遗憾的是,此类窗口对象不能用于确定或设置全屏模式 - 这必须通过“系统事件”应用程序上下文中进程对象报告的窗口对象来完成,因为它们只包含相关的“AXFullScreen”属性。 请务必注意,应用程序窗口集合(与进程窗口集合不同)仅适用于具有AppleScript支持的应用程序

  • 不幸的是,“系统事件”应用程序上下文中由进程对象公开的窗口集合表现得很奇怪:

    ○当应用程序不在最前面或其中一个非全屏窗口处于活动状态时,它只包含非全屏窗口

    ○相比之下,当应用程序位于最前面且其全屏窗口之一处于活动状态时,它只包含单个全屏窗口,即使是其他窗口(无论它们是全屏还是全屏)不存在。

    ○关联应用程序和进程窗口很棘手,因为只有应用程序窗口具有'id'属性;两种类型直接共享的唯一属性是“名称”(即窗口标题);这两种类型都包含大小信息,但格式不同。

    ○(此外,进程窗口永远不会包含隐藏窗口,而必须使用whose visible is true过滤应用程序窗口集合以排除隐藏窗口。)

  • 因此,如果您要处理给定应用程序的所有窗口,基本方法如下:

    ○激活应用程序。

    ○遍历所有(可见)应用程序窗口对象。

    ○将每个窗口设为前窗。

    ○等待相应的进程窗口以编程方式访问;如果窗口激活涉及全屏转换,这将花费很长时间。

    ○检查或更改流程窗口的全屏状态(value of attribute "AXFullScreen")。

  • 如果某个应用程序只有全屏窗口,AppleScript可能会感到困惑 前窗是什么:它报告的前窗可能不是 使用AppleScript或Cmd-tab激活应用程序时激活的那个。

  • 使用activate激活应用程序时,即使该应用程序的全屏窗口以前处于活动状态,也会激活目标应用程序的非全屏窗口(如果有)。 但是,您可以将index of全屏窗口设置为1以激活它。

答案 1 :(得分:5)

您可以在Lion中检测全屏:

tell application "System Events"
tell process "Safari"
get value of attribute "AXFullScreen" of window 1
end tell
end tell
display dialog result as text

(来自http://dougscripts.com/itunes/2011/07/detect-full-screen-mode/)。

答案 2 :(得分:4)

如果您想在全屏模式和普通模式之间切换,请使用此提示

tell application "iTunes"
    activate
    tell application "System Events" to tell window "iTunes" 
                                          of application process "iTunes"
        click (every button whose description contains "full screen")
    end tell
end tell

答案 3 :(得分:0)

另一种方法是假设您没有更改"输入全屏"的默认键盘快捷键。只是让系统事件调用该快捷方式(^⌘F)。与mklement0非常彻底的答案一样,这需要激活相关窗口。

例如,要在Safari中切换最前面窗口的全屏状态,请运行:

tell application "Safari" to activate
tell application "System Events"
        keystroke "f" using {command down, control down}
end tell

(因为问题是关于Lion:我正在运行macOS Sierra,但除非"进入全屏"以及"退出全屏"不可用Lion中的菜单选项,我希望这也可以在Lion中使用。如果Lion中有菜单选项但与键盘快捷键无关,则应该可以在系统偏好设置的键盘设置下添加快捷键。)