Gabor Gabor - 3 months ago 9
Objective-C Question

Notification when display gets connected or disconnected

I'm working on an OS X application that displays custom windows on all available spaces of all the connected displays.
I can get an array of the available display objects by calling [NSScreen screens].

What I'm currently missing is a way of telling if the user connects a display to or disconnects a screen from their system.

I have searched the Cocoa documentation for notifications that deal with a scenario like that without much luck, and I refuse to believe that there isn't some sort of system notification that gets posted when changing the number of displays connected to the system.

Any suggestions on how to solve this problem?

Answer

There are several ways to achieve that:
You could implement applicationDidChangeScreenParameters: in your app delegate (the method is part of the NSApplicationDelegateProtocol).
Another way is to listen for the NSApplicationDidChangeScreenParametersNotification sent by the default notification center [NSNotificationCenter defaultCenter].

Whenever your delegate method is called or you receive the notification, you can iterate over [NSScreen screens] and see if a display got connected or removed (you have to maintain a display list you can check against at program launch).

A non-Cocoa approach would be via Core Graphics Display services:
You have to implement a reconfiguration function and register it with CGDisplayRegisterReconfigurationCallback(CGDisplayReconfigurationCallBack cb, void* obj);

In your reconfiguration function you can query the state of the affected display. E.g.:

void DisplayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void* userInfo)
{
    if(display == someDisplayYouAreInterestedIn)
    {
        if(flags & kCGDisplaySetModeFlag)
        {
            ...
        }
        if(flags & kCGDisplayRemoveFlag)
        {
            ...
        }
        if(flags & kCGDisplayDisabledFlag)
        {
           ...
        }
    }
    if(flags & kCGDisplaySetModeFlag || flags & kCGDisplayDisabledFlag || flags & kCGDisplayRemoveFlag)
    {
        ...
    }
}