Check if Mission Control is Active

Unfortunately, Apple has never provided a public API to programmatically check if Mission Control is active. There are not too many use cases for such a check, but I have encountered one.

One of my apps is using a global hot key (using the DDHotkey library) so that the user can press the hot key and the app’s main window is displayed. However, if Mission Control is active while the hot key is pressed by the user, the app’s main window will be displayed but has no input focus, making it impossible to enter any text, click on any button etc.

So, I want to avoid showing my app’s main window at all when Mission Control is active. Some more or less exotic approaches have been discussed to achieve this despite the lack of an official API (see here and here, for example), but they should need at least a non-sandboxed app to work or enabled support for assistive devices.

It turns out that there is nevertheless an easy way to check if Mission Control is active (code snippet below): We just ask which windows are present on the screen. If there is a specific window present owned by the dock process and with a vertical origin of -1.0, this will be a “Dock Window” as shown by Mission Control only:

missioncontrol

Of course this is slightly hackish and might break in the future, but it is working fine as of today in OS X 10.10, also in a sandboxed app environment and without a need for privileges for assistive devices:

func missionControlIsActive() -> Bool
{
    var result: Bool = false
    let windowInfosRef = CGWindowListCopyWindowInfo(CGWindowListOption(kCGWindowListOptionOnScreenOnly),
        CGWindowID(0)) // CGWindowID(0) is equal to kCGNullWindowID
    let windowList: NSArray = windowInfosRef.takeRetainedValue() // We own the returned CFArrayRef
    for entry in windowList
    {
        if (entry.objectForKey("kCGWindowOwnerName") as! String) == "Dock"
        {
            var bounds: NSDictionary = entry.objectForKey("kCGWindowBounds") as! NSDictionary
            if (bounds.objectForKey("Y") as! NSNumber) == -1
            {
                result = true
            }
        }
    }
    return result
}