Objective-C: get menu information from external application - objective-c

I'm trying to write a Mac OS menu extra application that displays a contextual menu containing the currently active application's menu bar items, when the user presses some hotkey. The displaying of the contextual menu I can do fine, but I can't seem to get the currently active application's menu bar items. At the moment I'm using [[[NSWorkspace sharedWorkspace] runningApplications] filteredArrayUsingPredicate:] to get the active applications' name, but NSRunningApplication seems to contain precious little other information. Is there any way I can get information about application menus from an external application?
UPDATE:
Using the ScriptingBridge framework seems to work fairly well, if you're happy using AppleScript:
SystemEventsApplication* sevApp = [SBApplication applicationWithBundleIdentifier:#"com.apple.systemevents"];
SystemEventsProcess* proc = [[sevApp applicationProcesses] objectWithName:appName];
for (SystemEventsMenuBar* menuBar in proc.menuBars) {
for (SystemEventsMenuBarItem* menuBaritem in menuBar.menuBarItems) {
NSLog(#"%#", menuBaritem.name);
}
}
will print out a list of menus available from the application's menu bar. Haven't found a way to get the contextual menu, so I won't call this answered just yet...
This was useful too: https://robnapier.net/scripting-bridge

You can use AppleScript to simulate clicking a menu item like shown here, but I'm not sure if it's possible to dynamically grab the names of all the menu items, to use that method you need to already have the names hardcoded into the app.

Related

Remove tab-related functions from Window menu?

I'm customizing the menus in my Mac Catalyst app. I've added two items, as you can see in the following screen shot ("Set Window Size" and "Open Separate Document Viewer"). But I want to get rid of the default menu items that appear between these two items (the four tab-related functions).
In buildMenuWithBuilder, I can remove some items (child menus) like this:
[builder removeMenuForIdentifier:UIMenuMinimizeAndZoom];
But there is no defined identifier for the child menu containing the tab functions. More significantly, it doesn't yet exist when buildMenuWithBuilder runs. If I put this code at the end of that method...
UIMenu *test = [builder menuForIdentifier:UIMenuWindow];
NSArray *test2 = [test children];
...then test2 contains only two default menus, UIMenuMinimizeAndZoom and UIMenuBringAllToFront, plus my custom menus. So even if I had its identifier, I suspect removing it here would have no effect.
More oddly, it appears between my two custom menus, even though I'm adding those one after the other with insertChildMenu:atStartOfMenuForIdentifier:.
Finally, I noticed that when I open a second scene (in a new Mac window), these tab options disappear from the Window menu and don't come back. It seems that macOS is initially deciding these functions could be relevant to my app, but then when I open a scene, it decides they're not relevant and removes them. So I'm wondering if there is a way to tell macOS from the start not to include these menu items?
I thought this might be related to the NSWindow property tabbingMode, but setting my main window to NSWindowTabbingModeDisallowed makes no difference. My only Mac development experience is through Mac Catalyst, so I don't know what else to try.
I think if you disable tabs completely, they’ll go away. This is a bit of a hack because you need to call AppKit code, but an Apple engineer gave it to me:
Class _nswindow = NSClassFromString(#"NSWindow");
[_nswindow setAllowsAutomaticWindowTabbing:NO];

OS X: How can I forward contextual menu clicks from dock icon to another application?

Question: Is there any way for one app to programmatically access and activate the contextual menu items that can be accessed when right clicking on the dock icon of another application?
App A: Non-open source Mac App Store app that currently has no AppleScript support
App B: My own application, which I could write in Objective-C, AppleScript, Python, whatever...
When I right click on the dock icon for App A, I see contextual menu options for custom commands related to the function of that application. What I would like to do is to populate the contextual menu for App B with the same commands, which when accessed forward those commands to App A assuming that App A is open (even if its dock icon is hidden).
Is this sort of thing possible?
Here's an idea. Download LiveCode 6.6.1 (the version of which I know that it all works) and add a button to a new LiveCode document. Select the button and press command-E to edit the script. Enter the following synax (for testing):
on mouseUp
put "test" & cr & tab & "test1" into myMenu
set the iconMenu to myMenu
end mouseUp
on iconMenuPick theItem
if theItem contains "test1" then
answer "You chose" && theItem
end if
end iconMenuPick
This is useful, because you can also use AppleScript and GUI scripting with LiveCode. Let LiveCode be app B and have it control app A.

Disabling Menu Item

One of my e-books explains how to add a new menu item. Well, that's not very difficult to figure out. It's not difficult to figure out how to link an IBAction to a new menu item, either. But this book and Google search results don't explain how to disable a menu item. More particularly, I want to disable Preferences and Quit, depending on where window currently appears. If the application currently shows the Preferences window, I want to disable these menu items.
Suppose that I have an IBOutlet named preferencesMenu and then that I have
[preferencesMenu setEnabled:NO];
, that won't disable the menu item in question. So how do you disable a particular menu item?
Thank you for your advice.
Tom
NSMenuItems disable themselves automatically only if both their target and selector are nil and NULL respectively.
[preferencesMenu setTarget:nil];
[preferencesMenu setAction:NULL];
Which a quick test reveals leads to this:
Just set the target to nil. I'll do the job.
[preferencesMenu setTarget:nil];

Menu bar button panels in Cocoa?

When I click on buttons in the menu bar (such as "About Program") when the program is running a new window pops up displaying information. How do I edit the windows associated with the buttons?
In Interface builder I manage to load "Main Menu" which allows me to customize the menu bar, but it doesn't allow me to work with the windows associated with the buttons. How would I edit these windows?
Mac OSX Snow Leopard, Xcode 3.2.6
EDIT: I am not specifically asking for steps for the "About Panel". I am looking for a general procedure for editing panels associated with buttons in the menu bar. In addition to the "About" panel I would also want to work with panels such as the "Help" panel. The "About" panel was just an example.
The standard About panel isn't in your nib; it's generated within the framework.
You can change the text of the panel by writing a Credits.rtf or Credits.html file and including that in your app bundle. (You may already have Credits.rtf supplied by the project template. If so, you should just edit that.)
If you want to make more radical changes, you'll need to create your own panel and change your About menu item to show it instead.
As far as a general procedure...no, there's no single procedure that would let you customize any standard panel in the same way. They all have their own mechanisms (e.g. some can display more panes when plug-in components are installed; some provide APIs to hide or show certain parts; some, like the About box, use bundle filename conventions to decide what to do).
For the Help panel specifically...you can't change anything about it except the web page (i.e. the help content). The toolbar, etc. is all handled by Apple. I suggest looking at this documentation for more, which also links to other important documents:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/OnlineHelp/Concepts/ComprehenHelp.html%23//apple_ref/doc/uid/20000017-BBCCFHAC

Document-based-like application + updating fields/menus/etc when switching document?

I have an application with multiple documents opened at once (as different tabs), but not implemented the Cocoa way, with NSDocument etc
So, let's say, that application is a text editor : e.g. an NSTextView in each document/tab and a menu (in the MainMenu) with options (on/off) related to that particular document.
Scenarios :
The user clicks a menu item (option) and the option is applied to the
current tab
Now, the user switches tab and the options (of the menu) should be update according to current document's settings
How should I go about that in the most Cocoa-friendly way?
(I certainly CAN do it; though I'm interested in what could be a more efficient way (and my definitely isn't))
You can implement validateUserInterfaceItem: on NSDocument. Menu and toolbar items call it to check if they should be enabled or not. Read about Implementing Validation in general and Enabling Menu Items specifically.