Why does OSX/Cocoa dock icon revert to default before going away? - objective-c

I'm working on wrapping some Cocoa functionality in an Objective-C library that will be called from a cross-platform C library. One of my goals is to provide someone who does development in C on Linux with the ability to deploy to OSX without having to get into XCode, nib files, etc. I want them to be able to compile and link their code on OSX using the command line tools, and end up with a regular resizeable main window with the usual buttons and so on, an application menu and a dock icon that looks and behaves as expected, etc.
I'm working on OSX 10.8.5. I have XCode 5.0 installed. Here's my gcc --version output:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
I've figured out how to present a main window, how to set up the application menu, and various other things, programmatically, without using XCode or any nib or plist, but I've run into a problem with the dock icon.
I set a custom dock icon image by calling:
[NSApp setApplicationIconImage:dockImage];
When the user quits the app, the dock icon image reverts to something else (some kind of default application icon or view), briefly, before going away. How can I prevent that from happening without using XCode to create a nib or a plist?
I've tried setting the activation policy of NSApp to prohibitted in the app delegate's applicationShouldTerminate method, to try to hide the dock icon before this switch back occurs. That didn't help, it does hide the window and the dock icon, but the dock icon still switches back to the default icon, briefly, as part of the process of hiding. I confirmed this by returning NSTerminateLator, and confirming that setting the activation policy to prohibited does cause the dock and the icon to hide even though the app is not terminating, and not setting it leaves it unhidden.
I've tried subclassing NSApplication and overriding the setApplicationIconImage call. I have confirmed that it is being called a second time, by something other than my code (well, or not directly by my code, anyway), just before the program exits. I've tried preventing the second call to it from working by calling the super function the first time, but not the second time, and I've confirmed that code in that function can prevent my code from changing the application icon, but that didn't fix the problem. It still happens anyway, somehow.
I've also tried removing the application badge, like this:
[[window dockTile] setShowsApplicationBadge: NO];
just in case it was something to do with that, but that didn't work. The docs say that app badges are no longer relevant as of 10.6, but I was grasping at straws.
Being stumped on the programmatic front, I'm now trying to find out how to package an .app from scratch,without using XCode, and see if maybe I can create a plist from scratch that has a reference to application image in it. But a programmatic solution would be preferable, as I'd really like to minimize what goes into the OSX-specific packaging of a deployment.
Another possibility might be to use XCode once, to produce a very generic, bare-bones .app that my deployment scripts copy and alter.
Please don't shoot my question down as being "too broad" or "not constructive" or something like that. I realize I'm reinventing wheels that already exist in various forms, but there's no law against trying to build a better mouse trap, or just a different or even a worse one, for that matter. I realize I'm trying to fix a problem that a lot of people would consider inconsequential, but XCode-produced apps don't have this problem, and I really don't want the tools I'm creating to produce any user-visible artifacts like that. I'm not intending to diss Apple's tool chain or invite debate about whether or not what I'm pursuing should be pursued. I have a specific, technical problem that I'm looking for solution to that is within the constraints of my goals.

Related

NSMenuBar apps influencing (disabling) each others views (NSMenuItem's) ? BUG

I'm working on a NSMenuBar application and another NSMenuBar app seems to influence the display behaviour of my application!? More precisely: Adobe's Creative Cloud Application. When I click on that (creative cloud) Icon, the popup-view appears. Afterwards, when I click on my StatusBar Icon, my Menu appears, BUT, all the NSMenuItem's that should be Enabled are suddenly Disabled, and not interactive anymore.
Some observations:
When I log the enabled-state of the NSMenuItem, it logs correctly as being Enabled, but it is clearly not displaying as enabled (see screenshot), and clicking on it simply closes the Menu without performing the associated action. I do the logging with the following code:
-(void)menuWillOpen:(NSMenu *)menu
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
NSLog(#"preferences menu-item is enabled: %hhd",[self.preferenceMenuItem isEnabled]);
});
}
The NSMenu I use is set to setAutoenablesItems:NO.
Also, Adobe's Creative Cloud uses a popup-view. And when it is opened, It clearly hovers over the screen-real-estate that my NSMenu is using.
When I try to reproduce this with other NSMenuBar applications (e.g. Apple's Wifi or Bluetooth) it all works. No problem. Then again, those applications don't use Popover-views, and they don't completely overlap the space of my app.
Please see these screenshots as illustration:
Before
Malicious Creative Cloud
After
What Am I missing here? Apps should not be influencing each other like this right? I'm slowly but surely losing my mind over this. Any help MUCH appreciated! Thnx!!
I have found the solution to my own problem. So I hope I will help anybody else struggling with this.
I was using my main xib file menu (with the status-bar) and referenced that menu to open when clicking on the statusbar icon. This caused the app to get in focus and to display two times the same menu (although not open at the same time), one under the statusbar-icon as intended, and one on the left side next to the apple symbol. Whenever the statusbar-menu was somehow getting deactivated, the left menu was still working, as if the focus was shifted to that one.
For me the solution was to decouple my referenced menu from the xib's menu, by dragging it outside the parent-menu. It's weird because somehow it's not visible anymore in InterfaceBuilder, but it's definitely still there. See screenshots:
BEFORE:
AFTER:

Cocoa Background Mode When all windows closed

I am developing an OS X app
That uses StatusBar and Also has Windows
I would to move my app to "background" (That only StatusBar will be shown and windows ofc and not applications main menu)
When all it's windows are closed.
(I want to do it so, the app won't appear in cmd+tab menu etc, I want only StatusBar to be).
I am quite don't know where in documents to look for it and if it is even possible.
I have found that in Info.Plist I can put a flag to enable "LSBackgroundOnly" - then I see only my StatusBar.
But I want to switch between background and foreground, Since I want to allow my user to open the main Application Window via the StatusBar menu as well.
What would be the best approach or where to look for this ?
Sorry to flag as a possible duplicate. The other question doesn't exactly have good keywords for searching, but the answer is the same:
Use or modify the code in the answer here.
The info.plist settings are or OSX versions before 10.9 and cannot be changed at runtime. 10.9+ you can use NSApplication's setActivationPolicy and application delegate functions to do what you want. See discussion here and here as well.

Register Double-Click on Desktop (but not on Icons !)

Here's a though question:
I need to find out when the user double-clicked the OS X desktop, but not icons on it.
Now, I have thought of the following solutions, though I am not sure if they are doable:
Using desktop icons position (not sure how to get them), and the size of the desktop icons, we could theoretically check once the user double-clicks on the desktop, if it is inside one of the icon areas. Contra: Might not be flawless as some icons might be transparent or not taking up the entire icon size.
Maybe there is a variable that tells us if a icon from the desktop has been clicked? Then we could just check if that variable has been activated when the user double-clicked the last time the desk.
I am certainly still open to other (better) solutions, but they need to be sandboxable for the Mac App Store.
This is probably not going to be appropriate for the Mac App Store, for a number of reasons.
First, how are you going to intercept clicks outside your window? There are a few different mechanisms for this (e.g., event taps), but none of them are allowed in sandboxed apps. And that's intentional, and for a good reason—you're not supposed to be interfering with other apps or with the OS.
On top of that, it's hard to imagine that whatever you're trying to do wouldn't count as non-standard UI/HIG stuff, which is another reason for rejection.
But, assuming none of that were a problem, and you could intercept clicks on the desktop, there's no documented way to get all the icons on the desktop, so you have to read the .DS_store file directly, which means relying on private implementation information, which is another thing you're not allowed to do.
Finally, you have to get access to that .DS_store file. Unless you're expecting the user to drag the (invisible) file or its parent directory to your app or select it in an NSOpenPanel or something, the only way to get such access from inside the sandbox is via a temporary exception entitlement. Which you can't use unless you can justify to the reviewer why you need it as a workaround for a bug or limitation in the OS. So, what's your justification going to be?

Contextual Menu Plugins for Leopard OS

I am writing Contextual Menu Plugins for Leopard OS and referring Writing Contextual Menu Plugins for OS X, part 1 article by Brent Simmons. My plugin is working fine.
Is there any way to move my test menu into main menu (above the Label)?
The short answer is "no".
The OS controls what gets displayed in that menu, so in order to change it around, you would need to call private methods, reimplement system-level functionality, and just in general do some Very Bad Things which would be unsafe, could break at a moment's notice, and possibly work differently between even dot releases of the same OS.
Yes, it's called a system service, and was introduced in OS X 10.5. I know for a fact that many applications can do this, and Automator routines can be triggered this way because Automator itself is a system service. To see a service applicable for an application (i.e. Finder) go to the Application menu on the top bar (for lack of better name T_T), such as the Finder bolded text, and go down to Services > and it will show you all services that can be used in the app. If you need pointers on how to build this, just comment here.
EDIT: Yes, a SIMBL plugin is also considered a service, and on second read of your question, that's what you want.

Locking a screen in 10.6

How would I go about locking a screen like Keychain does, meaning preventing all access to Dock, menubar, desktop, etc. Basically just a black screen that I can add a password field to, for the user to return to the desktop? I am well aware of the Carbon method, but I want the NSApplication method because this is an all Cocoa application.
Thanks~
If you can get away with not writing this code yourself, all for the better. It is usually a terrible idea to write your own code to lock the screen, considering the number of vulnerabilities that have been found in screen locking code over the years. If you have a Carbon call that can do it, go ahead and use that... don't worry about the "purity" of your Cocoa code.
However, if you decide to write this yourself, here's what you do:
First, capture all the screens using CoreGraphics. See: http://developer.apple.com/mac/library/documentation/GraphicsImaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html
Next, create a new NSWindow and put it in front of the window that's used for capturing the screens. You'll have to call a CG function to get the "order" of the black window covering each screen, and order the new window in front of that. Normally, the black window has an order so far forward that everything is behind it. Put a password field in the window. Do NOT use an ordinary text field or write your own code for password input. The password input field has a ton of special code in it so you can't copy text out of it, and other programs can't listen to keystrokes while you're typing into a password field. So use the one that Apple provides.
Last, put the computer in "kiosk mode". This mode allows you to disable alt-tab, user switching, the menubar and dock, and even the ability to force quit. See: http://developer.apple.com/mac/library/technotes/KioskMode/Introduction/Introduction.html
It's not a lot of code, it just uses a few different APIs so you'll spend most of your time bouncing between API docs. I suggest writing the screen lock code as its own application (just add a new application target to your Xcode project) and then put the screen locker inside your application bundle. This used to be (as of 10.4) how Apple Remote Desktop implemented the "Lock Screen" functionality, but I can't find the app anymore.
I believe the Cocoa replacement to the SetSystemUIMode API was not introduced until 10.6.
If you can live with Snow-Leopard-only code, the answer is - setPresentationOptions: on NSApplication.