Mirek Fidler
Mirek Fidler

Reputation: 340

Minimal Cocoa application - problem with menu

I need to implement minimal Cocoa application without Xcode. I am trying this example:

https://www.cocoawithlove.com/2010/09/minimalist-cocoa-programming.html

#import <Cocoa/Cocoa.h>

int main()
{
    [NSAutoreleasePool new];
    [NSApplication sharedApplication];
    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
    id menubar = [[NSMenu new] autorelease];
    id appMenuItem = [[NSMenuItem new] autorelease];
    [menubar addItem:appMenuItem];
    [NSApp setMainMenu:menubar];
    id appMenu = [[NSMenu new] autorelease];
    id appName = [[NSProcessInfo processInfo] processName];
    id quitTitle = [@"Quit " stringByAppendingString:appName];
    id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle
        action:@selector(terminate:) keyEquivalent:@"q"] autorelease];
    [appMenu addItem:quitMenuItem];
    [appMenuItem setSubmenu:appMenu];
    id window = [[[NSWindow alloc] initWithContentRect:NSMakeRect(10, 10, 200, 200)
        styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO]
            autorelease];
    [window setTitle:appName];
    [window makeKeyAndOrderFront:nil];
    [NSApp activateIgnoringOtherApps:YES];
    [NSApp run];
    return 0;
}

It works well, except for one little problem: Immediately after the launch, menu is altered, but is inactive (clicking it does nothing). If I select some other application and then get back to that minimal one, menu starts working as expected.

Any idea how to fix this?

Upvotes: 2

Views: 514

Answers (3)

H. Katsura
H. Katsura

Reputation: 51

looks like NSApplicationActivationPolicyRegular and activateIgnoringOtherApps: were missing according to https://github.com/rgl/minimal-cocoa-app

here is the updated code:

// cc -o min-cocoa min-cocoa.m -framework Cocoa
#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [NSApplication sharedApplication];
        id menubar = [NSMenu new];
        id appMenuItem = [NSMenuItem new];
        [menubar addItem:appMenuItem];
        [NSApp setMainMenu:menubar];
        id appMenu = [NSMenu new];
        id appName = [[NSProcessInfo processInfo] processName];
        id quitTitle = [@"Quit " stringByAppendingString:appName];
        id quitMenuItem = [[NSMenuItem alloc] initWithTitle:quitTitle action:@selector(terminate:) keyEquivalent:@"q"] ;
        [appMenu addItem:quitMenuItem];
        [appMenuItem setSubmenu:appMenu];
        id window = [[NSWindow alloc] initWithContentRect:NSMakeRect(10, 10, 200, 200) styleMask:NSWindowStyleMaskTitled backing:NSBackingStoreBuffered defer:NO];
        [window setTitle:appName];
        [window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
        [window makeKeyAndOrderFront:nil];

        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];

        dispatch_async(dispatch_get_main_queue(), ^{
            [NSApp activateIgnoringOtherApps:YES];
        });

        [NSApp run];
    }
    return 0;
}

Upvotes: 0

eonil
eonil

Reputation: 85955

I have same problem for minimal apps. They do not process events properly.

At this point (10.15.2 (19C57)) these are what it requires to work properly.

  • Application bundle folder with .app extension. (maybe optional)
  • Contents/Info.plist with CFBundleIdentifier value. (no other key is required)
  • Contents/MacOS/(your-executable) file.

Upvotes: 1

l&#39;L&#39;l
l&#39;L&#39;l

Reputation: 47159

It appears to be a bug in macOS somewhere above version 10.8.5.

I tried the code (and similar variations within 10.13.6) and they all failed in the way you've described. Compiling the same code and running on version 10.8.5 does not have the same behavior and the menu can be accessed normally as one would expect.

Conclusion:

I would recommend reporting the behavior to Apple.

Side Note: You'll want to remove the autorelease portions of your code as ARC prohibits this and cannot be used with the latest Xcode SDK's.

Upvotes: 0

Related Questions