How do I check if OSX is in the process of logging out / shutting down? - macos

I'm writing a Qt application and there's a yet-unsolved bug where Qt doesn't pass notifications of logout/shutdown to apps in osx (it works in windows). When you logout/shutdown my app's windows are closed, I'd like to use that time to somehow query osx to see if it's in the process of logging out / shutting down.
Any ideas?

If you know how to register for notifications, you can register for the NSWorkspaceWillPowerOff notification, which will call your observer method when either a power-down or a logout is requested.

Related

Erlang wxWidgets app - Closing the beam.smp file once app finished

got a weird question which I haven't been able to find an answer to online so I'm trying my luck here.
I have a normal erlang application using wxWidgets, once I try to shut down my application I get the event that the wxServer has indeed entered the event which is connected to the window closing, I get a message that it is in the process of exiting, and my window does indeed close, but as shown in the picture below, the beam.smp on my toolbar doesn't close at all, I have to manually force the closing of the beam.smp file which sends a SIGTERM to the erlang terminal which also shuts down my erlang VM (which I have to reboot it later).
long story short, what am I missing on my close window event so that everything shuts down nicely without it crashing my erlang VM? I was able to read that wxWidgets behaves differently on macOS but I haven't been able to find how to correctly close the application.
handle_event(#wx{event = #wxClose{}},State = #state{frame = Frame,panel = Panel}) ->
io:format("Exiting~n"),
wxFrame:close(Frame),
wxFrame:destroy(Frame),
wx:destroy(),
{stop,normal,State};
You can close the emulator from code with init:stop/0,1
Also, if your application is started as permanent, it should suffice with terminating that application. Check the behaviour in erlang:application

applicationShouldTerminate: not called when system restarts

I have to run some code when the app is about to terminate. applicationShouldTerminate: runs when quit is selected from the menu or when I press Cmd Q but not when I restart the mac.
Is there a way to force applicationShouldTerminate when a user tries to restart the mac? Or is it another function being called in this scenario?
Your app might have Sudden Termination enabled.
macOS 10.6 and later includes a mechanism that allows the system to log out or shut down more quickly by, whenever possible, killing applications instead of requesting that they quit themselves.
...
Debugging tip
You can determine the value of the sudden termination using the following LLDB command.
print (long)[[NSClassFromString(#"NSProcessInfo") processInfo] _suddenTerminationDisablingCount]

Reacting upon iTunes launch with NSDistributedNotificationCenter

I'm trying to intercept when iTunes starts up on Mac OS X, so I can relaunch my application to work around few bugs in the iTunes Framework.
What I did is to temporarly disable the sandboxing of my application and listen to all NSDistributedNotificationCenter notifications in order to examine them and pick the ones I want.
What I found is that upon start iTunes apparently sends this event:
object: com.apple.iTunes.help name: HelpBookRegistrationDidChange userInfo: (null)
which seems rather unique but also doesn't give an exact clue it is related to a startup event only at 100%.
Does anyone know if this is safe way to intercept such event?
If so, once my app is sandboxed again I need to ask temporary permission to listen to this kind of event, how can I do that in code?
Do you believe scripting bridge can help in this case?
You don't need to disable sandboxing for this, just observe NSWorkspaceDidLaunchApplicationNotification in the notification center provided by NSWorkspace, not the distributed one.
You'll get an instance of NSRunningApplication in the user info of the notification, which you can use to determine whether the launched app was iTunes (use the bundleIdentifier property).

Detecting when Safari has launched

I'm trying to get my mac app to do something whenever Safari is launched. The obvious way to detect Safari launch is by polling for running processes. Is there a better way to do this?
I was thinking there might be some API that I could use to register callbacks on, or perhaps there's a notification center event that I can observe.
You can add yourself to NSWorkspace's notification center as an observer for NSWorkspaceDidLaunchApplicationNotification. When you receive the notification, examine the instance of NSRunningApplication it provides (object in the notification's userInfo for the key NSWorkspaceApplicationKey) to determine if it was Safari that was launched.
Check the NSDistributedNotificationCenter and NSWorkspace classes.
The following post might be helpful: How to Listen For an Application Launch Event in Mac OS X?

Request suspend on Vista but allow other applications to cancel

My application uses the Win32 SetSuspendState() API to trigger system suspend or hibernation when it has finished doing a lengthy task.
The API accepts a parameter "ForceCritical" which determines whether or not the system suspends immediately or whether it broadcasts PBT_APMQUERYSUSPEND first to allow other apps the chance to cancel the suspend. My app uses this to play nicely with other apps like Media Player, so it doesn't suspend if you're listening to music or something.
For some reason, starting with Vista, MS have changed things so this parameter is ignored so SetSuspendState immediately causes a suspend and other applications have no opportunity to stop it.
Does anyone know how I can get the desired "polite" behaviour back again on Vista?
MSDN says
To prevent the system from transitioning to a low-power state in Windows Vista, an application must call SetThreadExecutionState to inform the system that it is in use
I would guess that WMP does this, but older apps don't. You could probably emulate this by sending the WM_POWERBROADCAST:PBT_APMQUERYSUSPEND message to all top level windows and check their return values (Send the message with a timeout so a hung app does not hang your app)

Resources