gpt4 book ai didi

macos - 是否可以通过编程方式为 OS X 打开/关闭 "do not disturb"

转载 作者:行者123 更新时间:2023-12-03 16:01:19 28 4
gpt4 key购买 nike

是否可以以编程方式(即通过代码)打开/关闭 mac os x 的“请勿打扰”。我通过谷歌做了一些研究,例如:

  1. 通过 Automator 脚本 applescripting notification center scheduling do not disturb 。顺便说一句,我没有让它工作,当我杀死所有通知中心时,请勿打扰开关仍然处于关闭状态

  2. 通过代码写入默认值,programmatic equivalent of defaults write command e.g. how to use NSUserDefaults ,但是如何使用 args -currentHost (在上面链接的文章中提到)

最佳答案

不幸的是(但并不奇怪),没有公共(public) API 来处理用户的通知首选项,其中之一就是“请勿打扰”模式 (DND)。

尽管如此,如果您想在应用程序中提供打开和关闭 DND 的功能,那么您实际上并不算运气差:有三种方法供您选择。

#1。运行这个小 AppleScript 并查看结果

这是 philastokes 编写的 AppleScript考虑到单击菜单栏中的通知中心图标的选项完全符合我们的要求:它会切换 DND 模式!

(* Copyright © philastokes from applehelpwriter.com *)
(* Link: http://applehelpwriter.com/2014/12/10/applescript-toggle-notification-centre-yosemite *)

tell application "System Events"
tell application process "SystemUIServer"
try
(* Replace "Notification Center" with "NotificationCenter"
here if you're targeting OS X 10.10 *)
if exists menu bar item "Notification Center, Do Not Disturb enabled" of menu bar 2 then
key down option
(* Replace "Notification Center" with "NotificationCenter"
here if you're targeting OS X 10.10 *)
click menu bar item "Notification Center, Do Not Disturb enabled" of menu bar 2
key up option
else
key down option
click menu bar item "Notification Center" of menu bar 2
key up option
end if
on error
key up option
end try
end tell
end tell

Please note that you need to replace "Notification Center" with "NotificationCenter" everywhere if you're targeting OS X 10.10

Also, executing this code requires your application to have Accessibility enabled for it.

最后一步是将其包装到 Objctive-C/Swift 代码中:

NSString *source  = ... // the AppleScript code
NSAppleScript *script = [[NSAppleScript alloc] initWithSource: source];
NSDictionary *errorInfo = nil;
[script executeAndReturnError: &errorInfo];

#2。直接使用辅助功能API

我们可以使用系统中可用的 Accessibility API 自行处理用户交互,而不是让 AppleScript 引擎处理用户交互:

Executing this code requires your application to have Accessibility enabled for it.

pid_t SystemUIServerPID = [[NSRunningApplication runningApplicationsWithBundleIdentifier:
@"com.apple.systemuiserver"].firstObject processIdentifier];
assert(SystemUIServerPID != 0);

AXUIElementRef target = AXUIElementCreateApplication(SystemUIServerPID);
assert(target != nil);

CFArrayRef attributes = nil;
AXUIElementCopyAttributeNames(target, &attributes);
assert([(__bridge NSArray *)attributes containsObject: @"AXExtrasMenuBar"]);

CFTypeRef menubar;
AXUIElementCopyAttributeValue(target, CFSTR("AXExtrasMenuBar"), &menubar);

CFTypeRef children;
AXUIElementCopyAttributeValue(menubar, CFSTR("AXChildren"), &children);

// XXX: I hate mixing CF and Objective-C like this but it's just a PoC code.
// Anyway, I'm sorry
NSArray *items = (__bridge NSArray *)children;
for (id x in items) {
AXUIElementRef child = (__bridge AXUIElementRef)x;
CFTypeRef title;
AXUIElementCopyAttributeValue(child, CFSTR("AXTitle"), &title);
assert(CFGetTypeID(title) == CFStringGetTypeID());
// XXX: the proper check would be to match the whole "Notification Center" string,
// but on OS X 10.10 it's "NotificationCenter" (without the space in-between) and
// I don't feel like having two conditionals here
if (CFStringHasPrefix(title, CFSTR("Notification"))) {
optionKeyDown();
AXUIElementPerformAction(child, kAXPressAction);
optionKeyUp();
break;
}
}

其中 optionKeyDown()optionKeyUp()

#define kOptionKeyCode (58)

static void optionKeyDown(void)
{
CGEventRef e = CGEventCreateKeyboardEvent(NULL, kOptionKeyCode, true);
CGEventPost(kCGSessionEventTap, e);
CFRelease(e);
}

static void optionKeyUp(void)
{
CGEventRef e = CGEventCreateKeyboardEvent(NULL, kOptionKeyCode, false);
CGEventPost(kCGSessionEventTap, e);
CFRelease(e);
}

#3。让我们假装我们是Notifications.prefPane

您可能已经注意到,您可以通过通知首选项 Pane 将模式范围设置为 00:00 到 23:59 来启用 D​​ND 模式。禁用 DND 只需取消选中该复选框即可。

这是Notifications.prefPane的内容:

void turnDoNotDisturbOn(void)
{
// The trick is to set DND time range from 00:00 (0 minutes) to 23:59 (1439 minutes),
// so it will always be on
CFPreferencesSetValue(CFSTR("dndStart"), (__bridge CFPropertyListRef)(@(0.0f)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("dndEnd"), (__bridge CFPropertyListRef)(@(1440.f)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("doNotDisturb"), (__bridge CFPropertyListRef)(@(YES)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

// Notify all the related daemons that we have changed Do Not Disturb preferences
commitDoNotDisturbChanges();
}


void turnDoNotDisturbOff()
{
CFPreferencesSetValue(CFSTR("dndStart"), NULL,
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("dndEnd"), NULL,
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("doNotDisturb"), (__bridge CFPropertyListRef)(@(NO)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

commitDoNotDisturbChanges();
}

void commitDoNotDisturbChanges(void)
{
/// XXX: I'm using kCFPreferencesCurrentUser placeholder here which means that this code must
/// be run under regular user's account (not root/admin). If you're going to run this code
/// from a privileged helper, use kCFPreferencesAnyUser in order to toggle DND for all users
/// or drop privileges and use kCFPreferencesCurrentUser.
CFPreferencesSynchronize(CFSTR("com.apple.notificationcenterui"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
[[NSDistributedNotificationCenter defaultCenter] postNotificationName: @"com.apple.notificationcenterui.dndprefs_changed"
object: nil userInfo: nil
deliverImmediately: YES];
}

关于macos - 是否可以通过编程方式为 OS X 打开/关闭 "do not disturb",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25210120/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com