6

I've got a Qt application that (for reasons that are outside the scope of this question) launches each of its windows as a separate process.

This works fine, but under MacOS/X, each window/process shows up as a separate entry in the Dock. Thus when the user has a dozen windows open, there are a dozen identical icons in the Docks, which isn't very helpful (since it's hard to tell which is which, and the icons start to get small).

Is there some way to tell the Dock to group all of these processes together under a single Dock icon? (a Mac-specific API would be fine)

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234

2 Answers2

4

You can use the following snippet to hide the Dock tile of a process that is not active:

 - (void)applicationWillResignActive:(NSNotification *)notification
{
    ProcessSerialNumber psn = {0, kCurrentProcess};
    TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
    if([self.window isVisible])
    {
        [self.window performSelector:@selector(orderFrontRegardless) withObject:nil afterDelay:0.05];
    }
}

- (void)applicationWillBecomeActive:(NSNotification *)notification
{
    ProcessSerialNumber psn = {0, kCurrentProcess};
    TransformProcessType(&psn, kProcessTransformToForegroundApplication);
    SetFrontProcessWithOptions(&psn, kSetFrontProcessCausedByUser);
}

Just add the above code to your app delegate and the app's Dock icon will vanish when the process resigns active.
To keep the window visible after the process was turned into an UIElement application, send a orderFrontRegardless message. (Very hacky, I know - but that must be the price for the non-standard window/process handling)

Probably you should also maintain a Dock menu that allows your users to select hidden windows.
You could dynamically add entries from your "main" app. Details can be found in the "Dynamically Adding Menu Items With the Application Delegate" section of the Dock Tile Programming Guide.

Update:
I slightly changed the code sample above as the previous approach led to a non-responsive main menu after re-activating the app.

Community
  • 1
  • 1
Thomas Zoechling
  • 34,177
  • 3
  • 81
  • 112
  • Won't this also run into the problem where my window's menu bar goes away when the process enters UIElementApplication mode? – Jeremy Friesner Jun 24 '13 at 16:15
  • No, because the process automatically is transformed into a foreground process as soon as the app becomes active again (e.g. by clicking on a window). You will have to find a solution for closed/hidden windows though. You can easily test the behavior of the above code by putting it into the app delegate of an empty Xcode project. – Thomas Zoechling Jun 24 '13 at 16:25
  • I built the above code with an empty Xcode project... the dock icon disappeared when I clicked outside of the window, but when I gave the window the focus again, the menu bar was non-functional: I could see it, but clicking on it had no effect (i.e. the menus didn't drop down). :( – Jeremy Friesner Jun 24 '13 at 22:51
  • I updated the code - Can you try it again. I changed the TransformProcessType parameter to kProcessTransformToBackgroundApplication when sending the app into the background and added a manual call to SetFrontProcessWithOptions when bringing it into foreground. – Thomas Zoechling Jun 25 '13 at 06:26
  • It works better now, albeit with a slight flicker when the window loses focus. I'll see what I can do with this, thanks! – Jeremy Friesner Jun 25 '13 at 15:22
1

Call QSystemTrayIcon::hide().

If that doesn't work, here are some things you can try:


Use NSApplication's setActivationPolicy: method

Way 1: [NSApp setActivationPolicy: NSApplicationActivationPolicyAccessory];

Way 2: [NSApp setActivationPolicy: NSApplicationActivationPolicyProhibited];


OR

Use LSUIElement (LSUIElement=1).

You can also put this in your pfile: <key>LSUIElement</key> <string>1</string> or make Qt do it for you.


There is also some discussion about OSX menus on the Qt forums. In addition, you could try to use QFocusEvent to check when the app loses/gains focus and then update menus accordingly.


Sources

Community
  • 1
  • 1
user2448027
  • 1,628
  • 10
  • 11
  • This wasn't quite what I was hoping for but I think I can make it work -- in particular I can make all windows dock-window-hidden by default (using Info.plist) and then call setActivationPolicy on just one of them.... the tricky part will be making sure a dock icon remains after that one window is closed. So unless another (better) answer comes along in the next day or two I'll award the bounty to this one. – Jeremy Friesner Jun 18 '13 at 21:50
  • Oh, bother -- the technique described in my previous comment works to keep a window's icon out of the Dock, but it has the side effect of also preventing the window's menus from becoming visible when the window has the focus -- instead, the menu bar continues to display the menu-contents associated with whichever app previously had the focus. – Jeremy Friesner Jun 18 '13 at 22:29
  • @JeremyFriesner There is some discussion about menus on the Qt forums: http://qt-project.org/forums/viewthread/2416. I'm not sure if that helps, though. – user2448027 Jun 19 '13 at 06:01