当您从笔记本电脑上拔下具有更高分辨率的外接显示器时,窗口大多保留其宽度,但其大小会被剪切到macbook屏幕的(较小)高度。当您重新插入显示器时,它们的尺寸仍然非常小。
我的问题是:有没有什么方法可以迭代所有打开的窗口,保存它们的大小,并在监视器重新插入后恢复它们?
答案 0 :(得分:9)
以下AppleScript演示如何:
代码:
tell application "System Events"
set theProcesses to application processes
repeat with theProcess from 1 to count theProcesses
tell process theProcess
repeat with x from 1 to (count windows)
set windowPosition to position of window x
set windowSize to size of window x
set position of window x to {0, 0}
set size of window to {100, 100}
end repeat
end tell
end repeat
end tell
注意:脚本需要访问辅助设备(AfAD):
“系统偏好设置”→“通用访问”→“启用辅助设备访问”
编辑(回复评论)
从AppleScipt启用AfAD可能会改善用户体验,但每次执行脚本时都不会这样做,只有在禁用AfAD时才启用AfAD。在不通知用户的情况下启用功能是不好的做法,提示用户启用AfAD的权限。
示例:
set AccesEnables to do shell script "[ -e \"/private/var/db/.AccessibilityAPIEnabled\" ] && echo \"Yes\" || echo \"No\""
if (AccesEnables is equal to "No") then
set askUser to display dialog "This application requires access for assistive devices. Enable this feature?" default button 2
set answer to button returned of askUser
if answer is equal to "OK" then
do shell script "touch /private/var/db/.AccessibilityAPIEnabled" with administrator privileges
else
close
end if
end if
答案 1 :(得分:2)
AppleScript解决方案 - 参见Anne的答案 - 是迄今为止最简单的解决方案。
如果您想将此信息提供给无法依赖的朋友,以了解如何启用辅助访问,或者更广泛地分发,请添加以下行:
do shell script ¬
"touch /private/var/db/.AccessibilityAPIEnabled" ¬
with administrator privileges
这将弹出通常的auth对话框,然后使用权限打开辅助访问。
实际上可以在没有辅助访问的情况下执行此操作,但它需要在CoreGraphics / Quartz Window Services中使用私有函数,即CGSPrivate.h。
使用公共API,您可以轻松枚举所有窗口:
CFArrayRef windows =
CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly |
kCGWindowListExcludeDesktopElements,
kCGNullWindowID);
返回一个字典数组,每个字典包含一个kCGWindowBounds字典,它包含Height,Width,X和Y整数值。
但这些公共API严格是只读的。要实际移动窗口,你必须深入CGSPrivate.h来做这样的事情:
CGSConnection conn = _CGSDefaultConnection();
for (NSDictionary *window in windows) {
CGSWindow wid = (CGSWindow)[[window objectForKey:@"kCGWindowNumber"] intValue];
CGRect bounds;
CGRectMakeWithDictionaryRepresentation([window objectForKey:@"kCGWindowBounds"],
&bounds);
CGSMoveWindow(conn, wid, bounds.origin);
}
显然,这非常讨厌,如果你真的需要分发一个不能要求辅助访问的应用程序,你应该只考虑它。
你也可以对Window Server协议进行逆向工程并直接与它对话,但这甚至更糟糕。