Need notification of applicationWillUnhide - cocoa

I'm using Lion, and the applicationWillUnhide - applicationDidUnhide application delegate methods are not being called when expected.
I'm miniaturizing the app to the doc, and then clicking on the dock icon again, but they are not being called, and the application is being deminiaturized correctly.
Maybe this does not count as hiding? How can I catch this event?
Your help is greatly appreciated,
Jose.

You can’t minimise an application on OS X, only hide it. To observe your NSApplication’s hidden state use NSApplicationDidHideNotification and NSApplicationWillUnhideNotification. If these notifications don’t appear to be sent correctly, you’ll need to show us some code.
Or do you actually mean minimising windows? You’ll have to observe NSWindowWillMiniaturizeNotification/NSWindowDidMiniaturizeNotification and NSWindowDidDeminiaturizeNotification for that (as per the NSWindow class reference). Remember that you can pass nil for the object parameter of -[NSNotification addObserver:selector:name:object:] to observe the minimisation state of all your application’s windows.

Related

Mac - How to programmatically hide NSApplicationActivationPolicyAccessory or LSUIElement application?

I have a small Swift-based Cocoa app that I'm writing. It's a single window app, something like Spotlight/QuickSilver/Alfred. It's set as NSApplicationActivationPolicyAccessory (docs) (though I've tried the same thing using LSUIElement, which is equivalent). It's activated via a global hot key.
Everything works well, except that when it's active I can't hide the application using NSRunningApplication.currentApplication().hide().
The docs for the hide method say "The property of this value will be NO if the application has already quit, or if of a type that is unable to be hidden." (emphasis mine), and I'm getting a NO back (though I'm actually using Swift, so I'm getting false).
I can understand why a NSApplicationActivationPolicyProhibited app wouldn't be able to be hidden, since it's never active, but it's confusing to me that this would be the case with NSApplicationActivationPolicyAccessory too.
I tried myWindow.orderOut(self);, but that just hides the window without hiding my application and returning focus to the previous app.
I do store a reference to the previously active application, so if need be I can manually activate that app again, but I'm hoping there is a cleaner method of doing this.
Use NSApplication.sharedApplication().hide(nil). One would normally address the application object (instance of NSApplication) rather than an instance of NSRunningApplication to operate on the current app.
The manual solution is to store a reference to the previously active NSRunningApplication instance (called previouslyActiveApplication below), and then activate it when you want to deactivate your NSApplicationActivationPolicyAccessory application, like so:
previouslyActiveApplication!.activateWithOptions(NSApplicationActivationOptions.ActivateIgnoringOtherApps);

Can I know what called applicationShouldHandleReopen ?

I'm looking to differenciate a dock clic from a click on the app icon in the finder.
Can I know what called applicationShouldHandleReopen or is there another way to do it ?
applicationShouldHandleReopen:hasVisibleWindows: is sent to the application's delegate. Delegate messages are normally sent by the delegating object, which in this case would be the application object.
The application object sends that message to its delegate in order to handle the reopen-application Apple Event. So, to find the sender, install your own Apple Event handler for that event and get the sender from the event. (The sample code is in Pascal and uses Apple Event Manager, but you can translate it to Objective-C and NSAppleEventDescriptor.)
That said, what you're doing is very dubious from a UI perspective. Reopening is meant to do the same thing no matter which application is reopening you—and it is not limited to the Finder or the Dock. In the common case, it is literally the user trying to launch the app while it is already open.
It may make more sense to only do your “reopen” behavior when no windows are open. Cocoa's built-in document-based-apps support does this automatically; if you don't respond to applicationShouldHandleReopen:: or you return YES, the application tries to open a new document. You can perform the same check (it even tells you whether you have any windows open) and perform your desired behavior under the same condition.

Qt::X11BypassWindowManagerHint functionality on Windows

I'm currently developing a cross-plataform virtual keyboard. In linux i was able to do whatever i want, but in Windows i'm having problems to prevent the widget to obtain the keyboard focus.
In linux, using the window flag
Qt::X11BypassWindowManagerHint
the widget never gets the keyboard input, but of course, that flag does not work on Windows
Is there something equivalent to that flag or some method i can use instead?
any ideas would be appreciated
thanks in advance
I posted an answer to a similar question over in Make a floating QDockWidget unfocusable. On Win32 you don't really have the choice of bypassing the window manager completely, but you should be able to get most of the behavior you want by intercepting nativeEvent to handle WM_MOUSEACTIVATE.
I would try to ignore the event. I believe you need to ignore FocusIn on the main application window - not sure about the actual event, you might need to prototype it. You can do ignore events by either installing an event filter or manually re-implementing one of the event methods (possibly event itself). I don't know which is the preferred way though but I'd attempt the event filter first for this task: http://doc.trolltech.com/4.6/qobject.html#eventFilter
I've never tried to capture the keyboard focus event, but I have been able to successfully ignore escape keys in a QDialog to prevent users from accidentally closing the window. I believe it should be possible.

WM_POWERBROADCAST handler for CMainDlg in ATL app not invoked

I have an ATL app where I want to handle WM_POWERBROADCAST. I have a CMainDlg (CAxDialogImpl) in whose MSG_MAP I defined the handler.
BEGIN_MSG_MAP(CMainDlg)
...
MESSAGE_HANDLER(WM_POWERBROADCAST, OnPowerChange)
...
END_MSG_MAP()
However, the handler isn't invoked when I do things that should invoke it, for instance change power settings or put the machine to sleep.
Any ideas about what might be going on, and how to fix this? Does CMainDlg not get notified of power events, for some reason?
I suspect your dialog not being a top level window (WS_POPUP styled).
Just tested with a WTL AppWizard non modal dialog app that WM_POWERBROADCAST is received (without any registration) on AC plugged/unplugged.
Did you register to receive the power events?
To add to answers above, you might want to use Spy++ tool to make sure the messages of interest are posted to your application in first place. You will also see which windows they are posted to, and if it is your window where you are waiting for this message.

How do I get keyboard events in an NSStatusWindowLevel window while my application is not frontmost?

After creating a translucent window (based on example code by Matt Gemmell) I want to get keyboard events in this window. It seems that there are only keyboard events when my application is the active application while I want keyboard events even when my application isn't active but the window is visible.
Basically I want behavior like that provided by the Quicksilver application (by blacktree).
Does anybody have any hints on how to do this?
There are two options:
Use GetEventMonitorTarget() with a tacked-on Carbon run loop to grab keyboard events. Sample code is available on this page at CocoaDev.
Register an event trap with CGEventTapCreate. Sample code can be found in this thread from the Apple developer mailing list.
Edit: Note that these methods only work if you check off “Enable access for assistive devices” in the Universal Access preference pane.
A simpler route that may work better for you is to make your app background-only. The discussion on CocoaDev of the LSUIElement plist key explains how to set it up. Basically, your application will not appear in the dock or the app switcher, and will not replace the current application's menu bar when activated. From a user perspective it's never the 'active' application, but any windows you open can get activated and respond to events normally. The only caveat is that you'll never get to show your menu bar, so you'll probably have to set up an NSStatusItem (one of those icon menus that show up on the right side of the menu bar) to control (i.e. quit, bring up prefs, etc.) your application.
Edit: I completely forgot about the Non-Activating Panel checkbox in Interface Builder. You need to use an NSPanel instead of an NSWindow to get this choice. This setting lets your panel accept clicks and keyboard input without activating your application. I'm betting that some mix of this setting and the Carbon Hot Keys API is what QuickSilver is using for their UI.
Update:
Apple actually seems to have changed everything again starting with 10.5 BTW (I recently upgraded and my sample code did not work as before).
Now you can indeed only capture keydown events setting up an event tap if you are either root or assistive devices are enabled, regardless on which level you plan to capture and regardless if you selected to capture (which allows you to modify and even discard events) or to be listen only. You can still get information when flags have changed (actually even change these) and other events, but keydown under no other circumstances.
However, using the carbon event handler and the method RegisterEventHotKey() allows you to register a hotkey and you'll get notified when it is pressed, you neither need to be root for that nor do you need anything like assistive devices enabled. I think Quicksilver is probably doing it that way.

Resources