8

I am creating an app in which I want to give the user the ability to show or hide the dock icon at run time. I have a preferences window with a checkbox, setting a user default value, which fires the following code using KVO:

if (!hideDockIcon) {
    TransformProcessType(&psn, kProcessTransformToForegroundApplication);
} else {
    TransformProcessType(&psn, kProcessTransformToUIElementApplication);
}

This works, but when hiding, the preferences window is closed directly (which makes sense as it is now a background app). However, I noticed that MS's SkyDrive client manages to hide the icon while keeping the Preferences window open. I have not been able to find out how one would do that, anybody has an idea?

I also tried using [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular] and NSApplicationActivationPolicyAccessory/NSApplicationActivationPolicyProhibited but that doesn't work for me; Accessory doesn't hide the dock icon, Prohibited closes the window as well and seems to make [NSApp activateIgnoringOtherApps:YES] being ignored.

sgvd
  • 3,819
  • 18
  • 31
  • Look at the following answer: http://stackoverflow.com/questions/2832961/is-it-possible-to-hide-the-dock-icon-programmatically –  Nov 14 '12 at 13:56
  • I have, and at these: http://stackoverflow.com/search?q=kProcessTransformToUIElementApplication, and that is what I already do as you can see in my question, but none go into keeping a window open when transforming the process type. Unless you refer to the KioskMode link in that thread, which is for hiding the whole dock, not just one icon. – sgvd Nov 14 '12 at 15:11

2 Answers2

5

I stumbled upon this thread where the following is suggested to prevent a window from being hidden:

[window setCanHide:NO];

This just covers hiding. If your window gets closed, you might try to use the window delegate? There's a call that let's you prevent the window from being closed

- (BOOL)windowShouldClose:(id)sender
Michael Starke
  • 316
  • 4
  • 6
  • `setCanHide` does the trick, thanks! I tried `windowShouldclose` earlier, but it seems that one isn't fired when setting UIElement. – sgvd Nov 19 '12 at 09:33
  • Since you say, `setCanHide` works, the Applications just gets hidden and since the window in not closed the `windowShouldClose` delegate call isn't fired. – Michael Starke Nov 19 '12 at 10:12
1

I solved this problem by not activating the app in the same run loop turn:

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

Swift:

dispatch_async(dispatch_get_main_queue()) { 
    NSApp.activateIgnoringOtherApps(true)
}

I'm calling dispatch_async to schedule the block for execution in one of the next run loop turns a few nanoseconds later. This gives the process the chance to finish hiding itself.

WetFish
  • 1,172
  • 2
  • 11
  • 21
  • This does result in a momentary flicker as the app re-activates but it does work. For Swift 5 you would need to update it to `DispatchQueue.main.async { NSApp.activate(ignoringOtherApps: true)}` – Gerry Shaw Jan 16 '22 at 04:19