Open Notification Center programmatically on OS X - macos

Is there a way to open Notification Center on OS X from a Cocoa app?
We tried launching the Notification Center app, but that doesn't work.
Our app is not sandboxed, so we can do whatever is required.

You can open it using ScriptingBridge, but it's not an official API, so it might break someday.
It's a bit odd, but this only works with sandboxed apps. If your app is not sandboxed, you need Accessibility access.
1. Generate Header file
Open Terminal and run the following commands:
cd ~/Desktop/
sdef /System/Library/CoreServices/System\ Events.app | sdp -fh --basename SystemEvents
Copy the file "SystemEvents.h" from your Desktop into your project.
Xcode will show some errors or warnings for a few lines in this file. Just remove these lines.
2. Import ScriptingBridge framework and generated header file.
#import <ScriptingBridge/ScriptingBridge.h>
and
#import "SystemEvents.h"
3. Add code
SystemEventsApplication *systemEventsApp = (SystemEventsApplication *)[[SBApplication alloc] initWithBundleIdentifier:#"com.apple.systemevents"];
SystemEventsApplicationProcess *sysUIServer = [systemEventsApp.applicationProcesses objectWithName:#"SystemUIServer"];
SystemEventsMenuBarItem *item = nil;
for (SystemEventsMenuBar *menuBar in sysUIServer.menuBars) {
item = [menuBar.menuBarItems objectWithName:#"Notification Center"];
if (item != nil && [item.name isEqualToString:#"Notification Center"])
break;
}
[item clickAt:nil];
You can also replace line 4-9 with this code, if you're sure the menu bars won't change in the future:
SystemEventsMenuBarItem *item = [[[sysUIServer.menuBars objectAtLocation:#2] menuBarItems] objectWithName:#"Notification Center"];
4. Add temporary exception for sandbox
Open your projects .entitlements file and add "com.apple.security.temporary-exception.apple-events" as an array. Add "com.apple.systemevents" as String.
Switching to Today view
This requires your app to have Accessibility access, so it won't work in sandboxed apps. You can simply call this script instead of using ScriptingBridge:
tell application "System Events"
click menu bar item "Notification Center" of menu bar 2 of application process "SystemUIServer"
click radio button "Today" of radio group 1 of window "NotificationTableWindow" of application process "NotificationCenter"
end tell

No, unfortunately there is no support for opening the Notification Center. Supposedly because it wouldn't be annoying for the user to have it open without them wanting it to open

Related

how to implement "show recents" item on OS 10.9 and later

I notice on Mac, every app on docker, when it's not opened and ctrl click it, there will be a pop-up menu, inside has a menu item called "show recents", when open the app this item will become "show all windows". I want to know how to make it work cuz right now, when I click it on my own app, it has nothing to show.
I have tested using doc controller and use noteNewRecentDocumentURL: method, but still, both "open recent" item in "file" and "show recents" in docker, it doesn't show my url I just added.
I do not know, where you click on the app to show the menu. The recent documents list is shown
in the app's File menu in the submenu Open Recent
in the dock menu for the app as a list with one item per document
likely at some other places related to the app
However where it is shown, the list is automatically managed by [NSDocumentController sharedDocumentController], which is added to the project template for document-based applications. If you do not have a document-based application you should re-check, whether this would be the better choice. But you can use [NSDocumentController sharedDocumentController] in a non-document-based application as well:
In some situations, it is worthwhile to subclass NSDocumentController in non-NSDocument-based applications to get some of its features. For example, the NSDocumentController management of the Open Recent menu is useful in applications that don’t use subclasses of NSDocument.
Documentation
There is a section Managing the Open Recent Menu containing the description of the method -noteNewRecentDocumentURL: in the documentation of NSDocumentController. You have to send this message to the shared instance,
whenever you want to add an item to the recent docs list:
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:theURLOfTheDocYourAppOpens];
Please note:
Applications not based on NSDocument must also implement the application:openFile: method in the application delegate to handle requests from the Open Recent menu command.
If you do not want to use the document controller, you have to maintain the list yourself and add it to the different locations manually. You can start here. I do not recommend that.
Here's code for use with Xamarin.Mac.
// Add the file to the menu. Note creation of file url.
void AddFileToOpenRecentMenu(string filePath)
{
var fileUrl = NSUrl.FromFilename(filePath);
NSDocumentController.SharedDocumentController.NoteNewRecentDocumentURL(fileUrl);
}
// Open the file selected from the menu (in AppDelegate.cs)
[Export("application:openFile:")]
public override bool OpenFile(NSApplication sender, string filename)
{
var keepFileInMenu = ProcessFile(filename);
return keepFileInMenu;
}

How do I set the accessibility name for a QPushButton that just has an icon?

Qt version 4.8.1, building for Windows, I'm trying to get accessibility information to work correctly for some buttons I have.
I have a QPushButton in my main window, which has an icon, thusly:
m_restartBtn = new QPushButton();
QPixmap rpm(":/images/Restart32x32.png");
QIcon ricn(rpm);
m_restartBtn->setIcon(ricn);
m_restartBtn->setIconSize(rpm.rect().size());
// put it in a box in the main layout
QHBoxLayout *buttonBox = new QHBoxLayout;
ui->mainLayout->addLayout(buttonBox);
buttonBox->addWidget(m_restartBtn);
Now that button shows up correctly, and if I hook up the signals it works fine. But when I use the 'inspect.exe' (from the Win 7 SDK), I see that the button shows up, but has no name.
If I use setText instead of putting in an icon, the accessible name shows up correctly, but of course, I'm seeing text, not my icon. If I do both, then the accessible name works fine, but I get the text on screen, as one would expect.
I tried setObjectName and setWindowTitle just for laughs, and they of course didn't work.
Is there a proper way to set the accessible name for a QPushButton that only displays an icon?
My immediate goal is to remotely control the application for accessibility purposes. But I'd like the work to do double duty and get me full accessibility at the same time, so I don't have to do a separate effort later for accessibility.
You can use QWidget::setAccessibleName(const QString &name).
QPushButton *button = new QPushButton(this);
button->setAccessibleName("name");
Is this what you were looking for?

Open document by dropping it on document-based application icon in OS X

I'm making a document-based application where documents are application bundles.
I can open them through "File → Open" menu fine. But when I try to drop them on the Dock icon they get rejected and the icon doesn't highlight.
I've searched this issue and it seems like it should just work given that LSItemContentTypes property is specified. Here is my Info.plist excerpt:
CFBundleDocumentTypes = (
{ CFBundleTypeName = "Example";
CFBundleTypeRole = "Editor";
LSHandlerRank = "Alternate";
LSItemContentTypes = ( "com.apple.application-bundle" );
NSDocumentClass = "Example";
NSExportableTypes = ( "com.apple.application-bundle" );
},
);
(I am developing outside of Xcode, this is a TextMate-formatted plist file.)
Also I tried implementing application:openFile: and application:openFiles: on my app delegate but they never get called.
There are no warnings or other related messages in the log. What am I missing?
Perhaps you need to set LSTypeIsPackage to YES.
That's the only difference I see with your plist stuff and mine that opens packages.
After that, maybe you need to logout/login, restart the app, or whatever to "refresh the system/launch services"?

Cocoa button opens a System Preference page

In a OSX Cocoa app, I would like a button that would open the "speech" preference pane. Is that possible? I'm just trying to save them the time to go System Preferences > Speech > Text to Speech
One can even select specific sub item inside a pref pane.
Here is example to select Camera under Privacy pane:
NSURL *URL = [NSURL URLWithString:#"x-apple.systempreferences:com.apple.preference.security?Privacy_Camera"];
[[NSWorkspace sharedWorkspace] openURL:URL];
Some credit goes to following site: https://macosxautomation.com/system-prefs-links.html
List of URLs for reference (*updated for macOS Big Sur & Catalina & Mojave):
Accessibility Preference Pane
Main x-apple.systempreferences:com.apple.preference.universalaccess
Display x-apple.systempreferences:com.apple.preference.universalaccess?Seeing_Display
Zoom x-apple.systempreferences:com.apple.preference.universalaccess?Seeing_Zoom
VoiceOver x-apple.systempreferences:com.apple.preference.universalaccess?Seeing_VoiceOver
Descriptions x-apple.systempreferences:com.apple.preference.universalaccess?Media_Descriptions
Captions x-apple.systempreferences:com.apple.preference.universalaccess?Captioning
Audio x-apple.systempreferences:com.apple.preference.universalaccess?Hearing
Keyboard x-apple.systempreferences:com.apple.preference.universalaccess?Keyboard
Mouse & Trackpad x-apple.systempreferences:com.apple.preference.universalaccess?Mouse
Switch Control x-apple.systempreferences:com.apple.preference.universalaccess?Switch
Dictation x-apple.systempreferences:com.apple.preference.universalaccess?SpeakableItems
Security & Privacy Preference Pane
Main x-apple.systempreferences:com.apple.preference.security
General x-apple.systempreferences:com.apple.preference.security?General
FileVault x-apple.systempreferences:com.apple.preference.security?FDE
Firewall x-apple.systempreferences:com.apple.preference.security?Firewall
Advanced x-apple.systempreferences:com.apple.preference.security?Advanced
Privacy x-apple.systempreferences:com.apple.preference.security?Privacy
Privacy-Camera x-apple.systempreferences:com.apple.preference.security?Privacy_Camera
Privacy-Microphone x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone
Privacy-Automation x-apple.systempreferences:com.apple.preference.security?Privacy_Automation
Privacy-AllFiles x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles
Privacy-Accessibility x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility
Privacy-Assistive x-apple.systempreferences:com.apple.preference.security?Privacy_Assistive
Privacy-Location Services x-apple.systempreferences:com.apple.preference.security?Privacy_LocationServices
Privacy-SystemServices x-apple.systempreferences:com.apple.preference.security?Privacy_SystemServices
Privacy-Advertising x-apple.systempreferences:com.apple.preference.security?Privacy_Advertising
Privacy-Contacts x-apple.systempreferences:com.apple.preference.security?Privacy_Contacts
Privacy-Diagnostics & Usage x-apple.systempreferences:com.apple.preference.security?Privacy_Diagnostics
Privacy-Calendars x-apple.systempreferences:com.apple.preference.security?Privacy_Calendars
Privacy-Reminders x-apple.systempreferences:com.apple.preference.security?Privacy_Reminders
Privacy-Facebook x-apple.systempreferences:com.apple.preference.security?Privacy_Facebook
Privacy-LinkedIn x-apple.systempreferences:com.apple.preference.security?Privacy_LinkedIn
Privacy-Twitter x-apple.systempreferences:com.apple.preference.security?Privacy_Twitter
Privacy-Weibo x-apple.systempreferences:com.apple.preference.security?Privacy_Weibo
Privacy-Tencent Weibo x-apple.systempreferences:com.apple.preference.security?Privacy_TencentWeibo
macOS Catalina 10.15:
Privacy-ScreenCapture x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture
Privacy-DevTools x-apple.systempreferences:com.apple.preference.security?Privacy_DevTools
Privacy-InputMonitoring x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent
Privacy-DesktopFolder x-apple.systempreferences:com.apple.preference.security?Privacy_DesktopFolder
Privacy-DocumentsFolder x-apple.systempreferences:com.apple.preference.security?Privacy_DocumentsFolder
Privacy-DownloadsFolder x-apple.systempreferences:com.apple.preference.security?Privacy_DownloadsFolder
Privacy-NetworkVolume x-apple.systempreferences:com.apple.preference.security?Privacy_NetworkVolume
Privacy-RemovableVolume x-apple.systempreferences:com.apple.preference.security?Privacy_RemovableVolume
Privacy-SpeechRecognition x-apple.systempreferences:com.apple.preference.security?Privacy_SpeechRecognition
macOS Big Sur 10.11/10.16:
Privacy-Bluetooth x-apple.systempreferences:com.apple.preference.security?Privacy_Bluetooth
Privacy-Music x-apple.systempreferences:com.apple.preference.security?Privacy_Media
Privacy-Home x-apple.systempreferences:com.apple.preference.security?Privacy_HomeKit
macOS Monterey 12.0:
Privacy-DoNotDisturb x-apple.systempreferences:com.apple.preference.security?Privacy_Focus
macOS Ventura 13.0:
Privacy-AppBundles x-apple.systempreferences:com.apple.preference.security?Privacy_AppBundles
Privacy-ListenEvent x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent
Dictation & Speech Preference Pane
Dictation x-apple.systempreferences:com.apple.preference.speech?Dictation
Text to Speech x-apple.systempreferences:com.apple.preference.speech?TTS
Sharing Preference Pane
Main x-apple.systempreferences:com.apple.preferences.sharing
Screen Sharing x-apple.systempreferences:com.apple.preferences.sharing?Services_ScreenSharing
File Sharing x-apple.systempreferences:com.apple.preferences.sharing?Services_PersonalFileSharing
Printer Sharing x-apple.systempreferences:com.apple.preferences.sharing?Services_PrinterSharing
Remote Login x-apple.systempreferences:com.apple.preferences.sharing?Services_RemoteLogin
Remote Management x-apple.systempreferences:com.apple.preferences.sharing?Services_ARDService
Remote Apple Events x-apple.systempreferences:com.apple.preferences.sharing?Services_RemoteAppleEvent
Internet Sharing x-apple.systempreferences:com.apple.preferences.sharing?Internet
Bluetooth Sharing x-apple.systempreferences:com.apple.preferences.sharing?Services_BluetoothSharing
Software update x-apple.systempreferences:com.apple.preferences.softwareupdate?client=softwareupdateapp
All this is possible thanks to key in Info.plist in preferencePane + CFBundleURLTypes (CFBundleURLSchemes) x-apple.systempreferences (Info.plist) in System Preferences.app
NSPrefPaneAllowsXAppleSystemPreferencesURLScheme
As of 10.15 some of the keys are located in PrivacyTCCServices.plist (Security.prefPane)
As of 10.14 Mojave some Privacy keys ceased to exists. Mojave privacy list:
Catalina privacy list:
The following is a fairly easy (and reliable) way to at least get System Preferences open to the Speech.prefPane:
- (IBAction)openSpeechPrefs:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:
[NSURL fileURLWithPath:#"/System/Library/PreferencePanes/Speech.prefPane"]];
}
However, it won't necessarily be switched to the Text to Speech tab, but rather the last tab the user had selected.
It is possible to actually switch to the Text to Speech tab as well, but it's a bit more involved. You can use AppleScript to send commands to the System Preferences application, but using the ScriptingBridge.framework (See Scripting Bridge Programming Guide) is much faster.
You'll need to add the ScriptingBridge.framework to your project, and then use a command like the following in Terminal to generate a SBSystemPreferences.h header file to work with:
sdef "/Applications/System Preferences.app" | sdp -fh --basename SBSystemPreferences -o ~/Desktop/SBSystemPreferences.h
Add that SBSystemPreferences.h header to your project, then change -openSpeechPrefs: to the following:
- (IBAction)openSpeechPrefs:(id)sender {
SBSystemPreferencesApplication *systemPrefs =
[SBApplication applicationWithBundleIdentifier:#"com.apple.systempreferences"];
[systemPrefs activate];
SBElementArray *panes = [systemPrefs panes];
SBSystemPreferencesPane *speechPane = nil;
for (SBSystemPreferencesPane *pane in panes) {
if ([[pane id] isEqualToString:#"com.apple.preference.speech"]) {
speechPane = pane;
break;
}
}
[systemPrefs setCurrentPane:speechPane];
SBElementArray *anchors = [speechPane anchors];
for (SBSystemPreferencesAnchor *anchor in anchors) {
if ([anchor.name isEqualToString:#"TTS"]) {
[anchor reveal];
}
}
}
EDIT:
Sample project using the ScriptingBridge.framework method:
http://github.com/NSGod/OpenSystemPrefsTTS
For the guys who run into the same issue that I mentioned in the comment, just go to the ~/Desktop (cos I specify this position) and you'll see the SBSystemPreferences.h has been created.
However, in this header, some class declarations are missing. So you have to add this declarations explicitly.
In my case, class "item" is undefined. So add this:
#class SBSystemPreferencesItem;
Then compile it and see what's still missing, which declaration needs to be added.

Xcode & IB - Window Controller Method

I have 2 windows in an xcode project, A and B. A is to capture information, B is to display. I built the windows in IB.
I would like to create a method to control the submit from window A to close window A, and display window B fullscreen.
I am completely new to OBJ C and Cocoa, so Please explain this or provide example code...
If I want to do this, I know I need to create a file from within IB with my A and B to add to my project to add the code, or do I simply add a cocoa file .h and .m to the project. If so, what tells IB that these files correspond to the windows I already created in IB. Once the IBAction is completed I know how to link in IB, but I am at a loss as to how to proceed.
So from what it sounds, you need to declare (in .h):
- (IBAction) closeWindowA:(id)self;
Then tell your application what closeWindowA really does (in. m):
- (IBAction) closeWindowA {
// your code goes here. Look up method(s) for closing the window - don't know them by heart
}
Then, just connect your Button or whatever is triggering the action in Interface builder using the draggable connections. Hope this helps - I also have to recommend 'Cocoa Programming for Mac OSX' by Aaron Hillegas. Helps tremendously in understanding these kinds of things.

Resources