Key Window for background application - cocoa

I'm creating a backgrounded cocoa application. The only thing that it's missing is the ability to take text inputs!
I'm making the application backgrounded by setting "Application is background only" in the Info.plist
But no matter what I do I can't make any window the keyWindow.
makeKeyWindow
makeKeyAndOrderFront
Both don't work...
I know apps can do this, anyone have any idea how you can get background application to have a key window?

Try using LSUIElement:
LSUIElement (String - Mac OS X) specifies whether the application runs as an agent application. If this key is set to “1”, Launch Services runs the application as an agent application. Agent applications do not appear in the Dock or in the Force Quit window. Although they typically run as background applications, they can come to the foreground to present a user interface if desired. [..]
If you switch the plist editor to raw keys you will see that "Application is background only" is LSBackgroundOnly which is used for faceless applications.

Related

On OSX, how can I ensure that a command-line application shows up in the application switcher once it creates a window?

I'm working on a cross-platform command-line application (in C++ on
Win/Linux and ObjC++ on OSX) which sometimes creates an OpenGL
context. The OpenGL context and window creation code is obviously
different for the different platforms, but on OSX it's done through
NSOpenGLView and NSWindow. There's no nib, and it's not built with
Xcode (it uses a cross-platform build script).
On OSX, the window is created and works fine, but the OpenGL window
doesn't show up in the Application Switcher (Cmd-Tab). This means
that it's tricky to find the window if you 'lose it' behind other
windows, and can often only be found by going to Mission
Control/Expose.
My question is: is there a programmatic way (i.e. a message to send to
the NSWindow object or NSApplication) to ensure that a (unix-style)
command line application will show up in the Cmd-Tab list once the
window is created?
You need to transform the process from an accessory to a regular app. Call [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular].
Once you do that, though, the app will also have a menu bar when it's active. This is good because it's what users expect. However, you probably need to add appropriate items to the menus in that menu bar to get a decent user experience.
Your app will appear in the Dock as well as the Command-Tab application switcher. By default, an unbundled executable will get an icon that looks like a CRT display showing the word "exec". You can use [NSApp setApplicationIconImage:someImage] to set a better icon, although the Dock will revert to showing the generic executable icon briefly as the process exits.

Keep status bar app from showing icon in the dock

I created a status bar app for the mac a few weeks ago. However, whenever I run the app, the dock icon shows up alone with the item in the status bar. Is there a way to keep the app from appearing in the dock?
I can't write comments but to what #Michael Dautermann wrote I'd suggest using the LSUIElement key.
You've said that it's a status bar app, so it has a UI.
LSUIElement (String - OS X) specifies whether the app runs as an agent app. If this key is set to “1”, Launch Services runs the app as an agent app. Agent apps do not appear in the Dock or in the Force Quit window. Although they typically run as background apps, they can come to the foreground to present a user interface if desired. A click on a window belonging to an agent app brings that app forward to handle events.
The Dock and loginwindow are two apps that run as agent apps.
Despite what the docs say it is a String so you can also set this as bool.
Yes, set the LSBackgroundOnly key in your app's "Info.plist" file.

How to force windows to appear when pressing Ctrl-Tab, even though app is agent

I have a Cocoa application which I am running as an agent because it has a status bar component. When my application brings up a window, these windows don't appear in the list when I press Ctrl-Tab to cycle through applications.
Is there a way to force a window in my application to appear?
Not while it's an agent, because it can never become the active application. Agents are meant to have only minimal user interaction, so it's assumed that you won't have an agent window around long enough for the user to need to command-tab away from it. (I personally find this annoying, because I'm constantly losing crash report windows behind application windows for the same reason, but it does make sense.)
However, the app doesn't have to be running as an agent in order for the status bar item to work, so I would just set the LSUIElement flag to NO and be done with it. It can be a regular, non-agent app that just happens to instantiate a status bar item.
If you don't want the application to be able to become active except when a window is visible, then that's more involved. You'd probably need to separate the application and the agent into separate processes, and have the agent launch the application in order to display the window. Then make sure the application quits when the window is closed, leaving just the agent running. Arq (http://www.haystacksoftware.com/arq/) is one example of an app/agent pair that works this way, with perhaps a clearer distinction between the agent and the app than you're after.

Possible to tell if NSApplicationActivationPolicyProhibited application is active?

Using JUCE with TUIO, I'm developing a multi-touch utility to send "hot keys" commands to other applications (I am using a usb touch frame that sends TUIO messages). For instance, I provide an interface through which users can touch-and-hold to program a key combo and then tap that button to send the programmed key combo to another app. They way I accomplish this on OSX is by running my utility as a "background only" application (NSApplicationActivationPolicyProhibited). I use [NSWindow setCanHide: NO] so the GUI of my utility is visible even though it runs as a background app.
It works well except in the case that a window from another application is on top of mine. What happens is that touches get passed through that other app into mine- causing unintentional button pushes in my app. Normally, I could have my app only listen to the TUIO touch callback whenever is is the active application, [NSApp isActive]. But, since my app is background only, it is never active and I have no way to tell if another window is covering it to prevent touches.
So, is there any way for a "background only" app to be able to tell if it is on top of all other windows? Or, is there a way from within my app to get a list of all Cocoa windows from other applications and be able to tell if they are appearing on top of my "background only" app?
Also, does anyone know how I would go about all of the above in Windows? In other words, what is the Windows equivalent of NSApplicationActivationPolicyProhibited and would I be able to tell if it is covered by other applications' windows?

Helper Application

How do you create a GUI-Less Application that runs in the background without appearing in the dock or in the application switcher.
If it's a background application the still needs to interact with the user, see LSUIElement. If it's really just called to do some processing and never talks to the user at all, you can just make it a Foundation tool or really any other kind of plain vanilla program.
You need to set either LSUIElement (Application is Agent) or LSBackgroundOnly (Application is background only) in your app's Info.plist. LSUIElement is usually for status bar apps, and LSBackgroundOnly for apps that have no UI at all.
You can Apple's documentation on these flags here.

Resources