如何以编程方式更改Mac上的光标大小

时间:2013-01-24 21:12:04

标签: objective-c macos cursor

我希望能够在我的程序中设置Mac上游标大小的系统首选项(如“辅助功能首选项”中所示),然后在程序退出后将其设置回来。

有没有办法通常从应用程序设置游标大小(具体)或系统首选项?

1 个答案:

答案 0 :(得分:11)

首先,如果您只是在光标指向窗口/视图/窗口小部件时尝试获取更大的光标,那么您就错误地说了这个。以正确的方式阅读Introduction to Cursor Manager

其次,即使您认为自己实际上想要在程序运行时设置系统范围的光标,在开始之前要更仔细地考虑它。即使您的应用程序在后台或隐藏,光标也会保持很大。如果你对透明的生命周期理念(用户通常不会注意或关心你的应用程序之间的差异,你的应用程序之间的差异和你的应用程序已经退出)做了任何动作,那么这将是甚至更多令人困惑。如果两个应用程序试图这样做,会发生什么?等等。 (不用说,Apple会拒绝任何来自App Store的应用程序。)

第三,设置系统偏好并不实际做任何事情,直到系统读取该偏好的新时间。并且不能保证何时会发生这种情况。因此,除非您的应用程序满足于更改在用户之前可能不会生效的首选项,例如,再次注销并重新登录(然后在您退出后将其更改回来),否则它并非完全有用。< / p>

但如果这真的是你想做的......


设置系统偏好非常容易。 “系统偏好设置”修改的大多数值都在默认存储中。 “辅助功能”窗格中的大多数值都位于com.apple.universalaccess域中。光标大小的特定键是mouseDriverCursorSize

因此,要将光标从bash更改为max size:

defaults write com.apple.universalaccess mouseDriverCursorSize 4.0

ObjC有点单调乏味,但是这样(未经测试):

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *olddict = [defaults persistentDomainForName:@"com.apple.universalaccess"];
NSMutableDictionary *newdict = [olddict mutableCopy];
[newdict setObject:@4.0 forKey:@"mouseDriverCursorSize"];
[defaults setPersistentDomain:newdict forName:@"com.apple.universalaccess"];
[defaults synchronize]

那么,如果您想设置首选项,然后强制系统注意到更改,该怎么办?显然,系统偏好设置应用程序正在执行某些事情,您可以随时跟踪它确实看到它的功能。

通常,它所做的是调用一些没有记录或暴露的私人功能。并且它可能在不同的OS版本之间有所不同。无论如何,它的作用可能不是最好的。但是通过快速测试:

看起来调用CGSShowCursor是有效的,只要隐藏光标可以接受它是可以接受的。连续两次调用CGSGetGlobalCursorData似乎也有效,尽管我不知道它为什么要这样做。

当然这些CGSPrivate函数没有记录或暴露,但至少其他人已经对它们进行了逆向工程,所以你不必这样做。您所要做的就是从一些开源项目中借用代码(iTerm2拥有一套更完整的标题集),并在每次从Apple发布新的次要操作系统后进行测试,并调试不具备的黑魔法&# 39;为25%的用户工作,即使它适用于其他75%的用户(无法访问25%正在使用的机器,通常甚至无法获得体面的问题或答案)。

如果您想跟踪系统偏好设置,并且您在OS X中没有经验跟踪过程,最简单的方法是通过GUI工具仪器:

  • 启动系统偏好设置并导航至辅助功能,显示。
  • 启动Xcode 4.4或更高版本,转到&#34; Xcode&#34;菜单,选择&#34;打开开发人员工具&#34;,然后&#34;仪器&#34;。
  • 在乐器中,选择&#34; Mac OS X |所有&#34;部分,然后&#34;系统跟踪&#34;。
  • 在&#34; Target&#34;下拉,附加到&#34;系统偏好设置&#34;过程
  • 点击&#34;记录&#34;按钮,并等待几秒钟,以便停止沙滩球。
  • 拖动光标大小滑块。
  • 点击&#34;停止&#34;按钮,等待更长时间才能完成分析。
  • 阅读有关Instruments的扩展文档,了解如何找到所需内容。

但是,请记住,系统偏好设置可能没有调用特殊的系统调用来执行它所需的操作;它可以是,例如,将特定的马赫消息发送到窗口服务器任务。幸运的是,你可以从任何看似可能的东西向后走。通过这样做,我发现它似乎在UniversalAccessCore中调用UACursorSetScale,它在UAPreferencesSetValue中调用/System/Library/PrivateFrameworks/UniversalAccess.framework/Versions/A/Libraries/libUAPreferences.dylib,这个函数似乎执行CFPreferencesSetValue并发送{ {1}}。也许只是通知很重要?你可以通过在Xcode / gdb / lldb中的相关函数上放置断点并查看参数是什么来测试它。或者你可以弄清楚如何自己调用CFNotificationCenterPostNotification(我的第一个猜测是params与UAPreferencesSetValue相同)。

快速检查:它发送的通知是&#34; UniversalAccessDomainMouseSettingsDidChangeNotification&#34;使用CFPreferencesSetValue nilobject字典(如userInfo到默认的分布式通知中心,并在更改@{@"mouseDriverCursorSize": @1.8327533, @"pid": @12345}首选项后自己做同样的事情没有影响。此外,NSUserDefaults显然采用与UAPreferencesSetValue不同的参数,因为如果您传递明显的值,则会在CFPreferencesSetValue内发生崩溃,因此您可能需要在系统中断开调用首选项以查看它发送的内容。

如果你从这个开始就很舒服,那很好。如果没有,在你考虑尝试做这项工作之前,你需要学习很多东西。


另一种解决方法是通过脚本编写。如果您可以让系统偏好设置应用程序执行与鼠标相同的操作,那么您可以设置,对吧?

只要启用了UI脚本(请参阅&#34;启用辅助设备的访问权限&#34;复选框,您已经在系统偏好设置中查看了同一个窗格,或谷歌如何启用它以编程方式关闭(如果您具有root访问权限),通过系统事件,这很乏味,但很容易。

事实上,虽然系统偏好设置没有公开足够的细节来实际更改任何内容,但它 显示足以让我们导航到右侧窗格,这节省了许多UI脚本步骤。所以,这里是AppleScript做你想做的事情:

CFNotificationCenterPostNotification

使用NSAppleScript从ObjC运行 - 或者,如果您愿意,可以将其翻译为tell application "System Preferences" reveal anchor "Seeing_Display" of pane id "com.apple.preference.universalaccess" end tell tell application "System Events" set theSlider to slider "Cursor Size:" of group 1 of window 1 of application process "System Preferences" set stash to value of theSlider set value of theSlider to 4.0 stash end tell ScriptingBridge或其他您可以原生运行的内容 - 并且您可以完成。