Cocoa - programmatically go to foreground / background

I have an application with LSUIElement set to 1. It has a built-in editor, so I want the application to appear in the Cmd + Tab loop when the editor is open.

-(void)stepIntoForeground { if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) return; if (counter == 0) { ProcessSerialNumber psn = {0, kCurrentProcess}; OSStatus osstatus = TransformProcessType(&psn, kProcessTransformToForegroundApplication); if (osstatus == 0) { ++counter; } else { //... } } } -(void)stepIntoBackground { if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) return; if (counter == 0) return; if (counter == 1) { ProcessSerialNumber psn = {0, kCurrentProcess}; OSStatus osstatus = TransformProcessType(&psn, kProcessTransformToUIElementApplication); if (osstatus == 0) { --counter; } else { //.. } } } 

Problems:

  • there is also a dock icon (not a big deal);
  • there is also a menu, it is also not very important, but they do not always appear.

Is there a way to disable the menu altogether or make it always displayed in the foreground? Thanks in advance.

+2
source share
3 answers

This is how we do it. (Works 10.7+)

  1. DO NOT USE LSBackgroundOnly NOR LSUIElement in plist application
  2. Add and run your menu and NSStatusBar menu
  3. After the application has been initialized, but not yet shown, a window will take a place where you may need to show the first window, if any. We are using applicationDidFinishLaunching.

    • If you do not want to show any window after initializing the application

      [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

      at 10.9 you can finally use

      [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];

    • If you open any window after completing the application, just show the main window

  4. Maintaining a list of windows

  5. If the last window is closed, call

    [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

    at 10.9 you can finally use

    [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];

  6. When your first window is shown next time, call

    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
    [NSApp activateIgnoringOtherApps:YES];
    [[self window] makeKeyAndOrderFront:nil];

This should do the trick, if at least one application window is visible, you will have a menu, a dock icon with a status signal and the cmd + tab element with your application, if the last application window is closed, only your NSStatusBar element will remain.

Known issues:

  • The first step is important, because without this, if the system modal dialog suspends your launch (for example, your application is downloaded from the network and quarantined, a confirmation dialog may appear on the first launch depending on your security settings), your menu bar may not belong to your application after the first application window shown.

    Workaround : launching in a regular application (step 1.) will solve this problem, but will cause another small one, your application icon may appear momentarily in the dock at startup, even if you want to launch without the window shown. (but we can deal with this without bearing in mind that the menu was a more serious problem for us, so we chose this instead)

  • Changing between NSApplicationActivationPolicyRegular and NSApplicationActivationPolicyAccessory (or NSApplicationActivationPolicyProhibited on OSes below 10.9) will kill your status bar menu item tooltip, the tooltip will be shown initially, but never after the second call to NSApplicationActivationPolicyAccessory → NSApplicationAct

    Solution: We could not find a working workaround for this and informed Apple as an error.

  • Switching from NSApplicationActivationPolicyRegular to NSApplicationActivationPolicyAccessory has other problems in some OS versions, for example, sometimes there are no more mouse events in explicit application windows

    Workaround : Go to the first NSApplicationActivationPolicyProhibited (taking care of this leads to unwanted application messages like NSApplicationWillResignActiveNotification, NSWindowDidResignMainNotification, etc.!)

  • The transition from NSApplicationActivationPolicyAccessory to NSApplicationActivationPolicyRegular is dummy, as on some versions of the OS

    • application main menu is frozen until the first application status changes
    • an application activated after this policy is not always placed in front of the application order

    Workaround : Go to the first NSApplicationActivationPolicyProhibited, take care of the limit switch until the desired NSApplicationActivationPolicyRegular follows Mafe with a delay, use fĂŠ dispatch_async or similar

+12
source

With fast 4, in applicationDidfinishLaunching (_: Notification)

 NSApplication.shared.setActivationPolicy(.regular) 

did the trick for me, but I was just trying to focus the keyboard on my programmatic window. Thanks.

+1
source

You can set the Application Agent (UIElement) application to YES in your plist file.

EDIT:

I think there are some hacks for this. But it really is not as it should have been. The cmd + tab is designed to get the application to the foreground, but if you do not have a menu bar, it does not look like the foreground for the user.

I would prefer to make a menu bar to access the application.

0
source

Source: https://habr.com/ru/post/917144/


All Articles