OSX Lion AppleScript:如何从任务控制中获取当前空间#?
Posted
技术标签:
【中文标题】OSX Lion AppleScript:如何从任务控制中获取当前空间#?【英文标题】:OSX Lion AppleScript : How to get current space # from mission control? 【发布时间】:2011-10-09 18:24:56 【问题描述】:我试图弄清楚如何从任务控制中获取当前空间#。来源会有所帮助,但更有帮助的是有关如何自己解决这个问题的信息。我写了一些applescripts,但似乎任何时候我都需要做一些新的事情(我找不到字典文档)它属于“告诉这个特定的应用程序”的类别(例如“系统事件“)这个非常具体的事情”,我不知道我该如何弄清楚。
特别是我想要做的事情:
我讨厌 OSX 10.7 中的新任务控制。我希望我的空间“网格”回来,因为我一直在使用它。我曾经每隔几秒钟使用箭头键(例如 ALT+↑)在空格之间导航。现在我被这个笨重的 1x9 空间阵列所困扰,而不是优雅的 3x3 网格。我重新映射了所有空间以使用数字键盘,这部分解决了问题(因为它是 3x3 网格),但仅在我连接了外部键盘时。
基本上,我希望能够再次使用 ALT+↑ 和 ↓,但要这样做我需要检测当前space # 这样我就可以从空间 5-->2 切换,例如。
Dave 在下面的回答虽然比我预期的要详细得多,但需要编写一个应用程序才能做到这一点(而且它仍然不能完全回答这个问题)。如果可能的话,我宁愿将几个键绑定到一个applescript。
【问题讨论】:
【参考方案1】:我正在尝试自己解决这个问题。还没有,但方向正确:
每个任务控制“空间”都有一个分配给它的uuid
...
...除了第一个 (AFAIK) 和仪表板。
你可以在这里阅读:
$ defaults read com.apple.spaces
$ defaults read com.apple.desktop
文件位置:
~/Library/Preferences/com.apple.spaces.plist
~/Library/Preferences/com.apple.desktop.plist
这是我的。我启用了四个空格,并显示了三个条目:
$ defaults read com.apple.spaces
spaces = (
type = 0;
uuid = "9F552977-3DB0-43E5-8753-E45AC4C61973";
,
type = 0;
uuid = "44C8072A-7DC9-4E83-94DD-BDEAF333C924";
,
type = 0;
uuid = "6FADBDFE-4CE8-4FC9-B535-40D7CC3C4C58";
);
如果您删除一个空格,该条目将从文件中删除。如果添加空格,则会添加一个条目。同样,桌面 1 或仪表板永远不会有条目。
我不确定是否有公共 API 可以确定显示器上显示的空间 uuid
。我假设 no uuid
表示 Display 1,而其他人的意思是 Display 1+n。
我快速浏览了 AppleScript 编辑器库(窗口 ---> 库),在系统事件下没有看到 spaces
的任何条目。这可能是 Cocoa 可以完成的事情,也许是通过私有 API,但我不确定 AppleScript。
更新 - 2011 年 7 月 23 日
看起来 Dock 控制着 Mission Control。你可以像这样获取它的头文件:
-
转至:
/System/Library/CoreServices/Dock
右键单击并显示包内容
导航:/Contents/MacOS/
将Dock
二进制文件复制并粘贴到您的桌面。
运行:$class-dump ~/Desktop/Dock
这会吐出它的所有头文件(它很长;将近 7,500 行)。您可以看到其中出现了spaceUUID
字符串。有一个名为 WVSpace
的类,它似乎代表 Mission Control 中的一个 Space,以及许多其他 WV* 类。
我明天继续看;现在太累了。 :)
更新 - 2011 年 7 月 24 日
在 Dock 中有一个名为 WVSpaces
的类。它具有许多属性,包括:
WVSpace *currentSpace;
unsigned int currentWorkspace;
WVSpace *nextSpace; // Space on the right???
WVSpace *previousSpace; // Space on the left???
BOOL currentSpaceIsDashboard;
BOOL dashboardIsCurrent;
...lots more...
每个WVSpace
类都有一个NSString *_uuid;
属性,这很可能是它的SpaceUUID。所以理论上你可以像这样得到当前的空间号:
WVSpace *currentSpace = [[WVSpaces sharedInstance] currentSpace];
NSString *currentSpaceUUID = [currentSpace _uuid]; // Empty string if main space???
诀窍是,如何访问隐藏在 Dock 中的私有 WVSpaces
类?我假设它是 Singleton,因为它有一个 NSMutableArray *_spaces;
属性,其中可能列出了每个空格。一次只显示一个空间(如果您使用多台显示器,这也是如此;空间跨越它们),因此只有一个 WVSpaces
实例是有意义的。
所以看起来它需要对 Dock 进行一些 SIMBL 黑客攻击才能访问 WVSpaces
。
【讨论】:
感谢您的信息。知道当前选择的 uuid 可能在哪里吗?我无法想象它会在一个 plist 中。仅供参考,我只是看了看,它们肯定是随机生成的 uuid。如果您删除桌面#然后重新添加它,它们会发生变化。你深究这个的理由是什么? :) 我添加了一些我发现的更多信息。很高兴知道 UUID 是唯一且非持久的。我正在研究这个我正在编写的程序,这暂时还是个秘密。 ;) 仅供参考,Apple API 中的所有 UUID 将在每次生成/请求 UUID 时随机生成,无论使用如何。 “在工厂”永远不会分配 UUID,因为这可能会在两个应用程序或设备通信时导致 UUID 冲突。 UUID 的全部意义在于唯一标识特定对象的特定实例。 很遗憾没有。有一种破解方法可以提取它,但它在 OSX 10.8 中被破坏了。在 10.8 之前,您需要注册@"NSWorkspaceActiveSpaceDidChangeNotification"
通知。收到后,您将通过CGWindowListCopyWindowInfo()
遍历所有NSWindow,并为每个窗口读取@"kCGWindowWorkspace"
的值,其中包含其工作区编号。这是一个可选键,因此并非所有窗口都返回某些内容,但您“通常”可以获取所有工作区 ID 的列表。但在 10.8 中,所有窗口的值都返回 nil,因此它不再起作用。【参考方案2】:
我一直在四处寻找,我想出了这个:https://gist.github.com/1129406
空格有一个不连续的 ID 和一个连续的索引(从 0 开始)。您可以通过两种方式获取 ID:
来自公共 API(请参阅get_space_id
)
来自私有 CGS API CGSGetWorkspace
您可以使用公共 API 按索引设置当前空间(尽管通知本身并未公开记录):请参阅 set_space_by_index
您可以使用私有 CGS API CGSSetWorkspace
按 ID 设置当前空间。
您无法直接获取当前空间索引。但是,如果您始终使用同一组九个空格,您可以使用set_space_by_index
旋转一次,收集它们的 ID,并构建映射。然后就可以从ID中获取当前索引了。
【讨论】:
@cocoacoder - Mountain Lion 上存在 API,但没有执行或返回任何有用的内容。【参考方案3】:...也一直在做这个:)
你说你“需要检测当前空间#”。这并不完全正确:要向下移动一行,您只需向右移动 3 个空格,因此原则上您可以绑定类似
tell application "System Events" to tell process "WindowServer"
key code 124, 124, 124 using control down
end tell
到 Alt-down(使用 FastScripts、Alfred 或其他一些避免 Automator 开销的快速方法)。当然,如果你在最后一排被击中,这种方法将失败——但如果你真的是硬连线,你永远不会这样做:)
您必须在通用访问首选项窗格中“启用辅助设备访问”,key code
方法才能工作。
警告:这不起作用。当我启动上面的脚本时,我很好地跳了三个空格。问题是之后我的键盘没有响应:似乎只有窗口管理器在接收事件:我可以关闭窗口和切换空间,但我无法与任何应用程序交互。 我的理论是,当跳转导致当前应用程序在脚本执行期间发生变化时,就会发生这种情况——但我不知道如何解决这个问题。
相关观察:Mission Control
(即/Applications/Mission Control.app/Contents/MacOS/Mission\ Control
)似乎对某些命令行参数有反应:
Mission\ Control
: 显示任务控制
Mission\ Control 1
: 显示桌面
Mission\ Control 2
: 显示当前应用程序窗口
我尝试输入来自defaults read com.apple.spaces
的一些 UUID,但这并没有起到多大作用。在黑暗中摸索就够了。
【讨论】:
【参考方案4】:我写了一个应用程序 - 它对你有用吗?
Change Space.app
实现它的关键是 control-shift 和箭头键,但如果您卡在 ALT 上,这可能是可以修复的。
确保在开始之前设置了 9 个空格(桌面),并且您需要将系统偏好设置中的默认 ctrl-up 和 ctrl-down 键绑定更改为其他内容(在键盘 -> 键盘快捷键 - > 任务控制:任务控制和显示桌面)。
在第一次运行时,它会循环遍历您的桌面,以便在您第一次更改空间时枚举它们。
那么您应该能够像在 3x3 网格中那样在桌面之间进行切换。
可能会有一些皱纹,但基本上是可以使用的,至少对我来说是这样。
【讨论】:
非常好(我是 TotalSpaces 的用户和粉丝),但我认为这里的想法是以编程方式,因为它提到苹果脚本。我记得 TS 有一个 API,但我不记得你是否可以控制它,或者只是从 API 中提取信息(我记录了我每个空间中发生的事情,所以如果我的机器崩溃了,我可以更轻松地将事情安排为我让他们在崩溃前)。也许您可以对此发表评论并举例说明如何做到这一点。 另外,在 TS 网站上几乎没有提到 API。也许你可以在那里添加文档?【参考方案5】:http://switchstep.com/ReSpaceApp
这很有效,是免费的(现在)而且很棒。
请务必手动创建与您的布局(在首选项中)预期一样多的空间。
【讨论】:
现在是 TotalSpaces,18 美元。不过,这是值得的。除了“Choosy”之外,TotalSpaces 是我几乎离不开的唯一实用程序。【参考方案6】:我在 Mountain Lion 上,这似乎对我有用。
defaults read com.apple.spaces
查找“当前空间”。您会注意到,使用不同的活动空间运行此命令不会更改当前空间,但是如果您选中并取消选中“系统偏好设置”中的复选框按钮并再次运行它,您会看到它已更新。
希望这对其他人有帮助!
编辑:它很难看,但我正在使用这个:
killall Dock && sleep 0.2 && defaults read com.apple.spaces | grep -A1 "Current Space" | tail -1 | awk 'print $NF ' | cut -f1 -d';'
【讨论】:
'如果您选中和取消选中“系统偏好设置”中的复选框按钮' - 你能详细说明吗?【参考方案7】:on openNewSpace()
tell application "System Events"
—start mission control
do shell script "/Applications/Mission\\ Control.app/Contents/MacOS/Mission\\ Control"
tell process "Dock"
set countSpaces to count buttons of list 1 of group 1
--new space
click button 1 of group 1
--switch to new space
repeat until (count buttons of list 1 of group 1) = (countSpaces + 1)
end repeat
click button (countSpaces + 1) of list 1 of group 1
end tell
end tell
end openNewSpace
【讨论】:
【参考方案8】:我已经在 macOS Catalina 中为自己想出了一个解决方法,尽管我希望这应该适用于多个 macOS 版本。这个解决方案解决了我的问题,即:
-
无法识别哪个桌面包含哪个项目,因为无法命名桌面。 (我通常同时将时间分配给多个项目,每个桌面都专门用于不同的项目[而且它们都使用相同的应用程序])
无法以编程方式(/轻松)随时确定我在哪个桌面上
缺乏工具来跟踪每个桌面所花费的时间
很久以前我使用 Stickies.app 解决了第 1 项。我将项目名称放在足够大的字体中,以便在任务控制中的桌面缩略图中很容易辨认,并将便签窗口隐藏在我的 Dock 后面,专门分配给相应项目的桌面。 (我还将桌面名称复制为从 Dock 左侧下方伸出的小上标文本,以便我可以识别任务控制之外的当前桌面。)
我刚刚通过applescript解决了第2项。在便签中,我添加了一个很小的、不显眼的字体字符串,将便签标识为桌面名称,例如'dtop'。例如。 “small_superscripted_name LARGE_NAME tiny_dtop_string”或“project1 PROJECT1 dtop”。请注意,此脚本假定项目名称不包含空格(即只有一个单词)。如果您愿意,您可以拆分为不同的字符/字符串。这是运行时生成桌面名称的applescript:
tell application "System Events"
--obtain the stickie with the desktop name
set dstr to name of first item of (windows of application process "Stickies" of application "System Events" whose name contains "dtop")
--Parse the desktop name from the stickie
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " "
set dname to first item of (dstr's text items)
set AppleScript's text item delimiters to astid
--Show the result in a dialog window
display dialog "Desktop: " & dname
end tell
就第 3 项而言,我还没有实现它,但我可以通过使用 osascript 调用脚本轻松地通过 cron 作业进行轮询。但是,我可能会探索映射我用来触发脚本的桌面键盘快捷键的可能性,例如,在 control-right/left-arrow 后 1 秒、F3 或 control-up-arrow 后 10 秒后延迟。 (它不会捕获触发桌面更改的窗口拖动,但自从我开始使用 2 个显示器以来,它一直没有起作用。)
设置完成后,我可能会将桌面名称和时间戳输出到日志中,以便跟踪在每个桌面上花费的时间。
【讨论】:
以上是关于OSX Lion AppleScript:如何从任务控制中获取当前空间#?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 XAMPP mac osx lion 中设置 memcache
Applescript启动XAMPP osx,弹出时不会输入密码?