Detecting connected screens

Hello macscripter community (my first post here!)

I’m trying to make a script that can execute a task as soon as I connect or disconnect a screen to my Mac.
I already have two working scripts but I’m not yet happy with them.
The difficult part is to count the displays that are connected.

One method was to use “Extra Suites” and ES screen count.
I wouldn’t mind to pay 10$ for Extra Suite but if there is an other way i’ll take it.

Second method comes from this link: http://stackoverflow.com/questions/559009/applescript-multiple-monitors-and-maximum-window-sizes
As suggested by the author a created an empty AppleScript application in Xcode and called it ASSAccess.
Here is my code:

tell application "ASSAccess"
	-- The first item in this list will be your main monitor
	set screensArray to call method "screens" of class "NSScreen"
	set startnumDisplay to screensArray count
	
	repeat
		set screensArray to call method "screens" of class "NSScreen"
		set numDisplay to screensArray count
		
		tell application "System Events"
			
			if startnumDisplay is not equal to numDisplay then
				set startnumDisplay to numDisplay
				-- return "newDisplay"
				-- DO SOMTHING HERE
			end if
			delay 10
		end tell
	end repeat
	
end tell

This also works but I have to open two applications (ASSAccess and my Code).
Isn’t there a way to combine the two?
Or maybe an even more simple way to detect the dis-/ connection of a screen?

cheers,
broenni

Hi,

you can gather the number of connected displays with Image Events


tell application "Image Events"
	launch
	set countDisplays to count displays
	quit
end tell

An automatic detection is possible only in ObjC respectively with the CoreGraphics function CGDisplayRegisterReconfigurationCallback
http://developer.apple.com/documentation/GraphicsImaging/Conceptual/QuartzDisplayServicesConceptual/Articles/Notification.html#//apple_ref/doc/uid/TP40004235-SW1

PS: this is a sophisticated solution for a AppleScript Studio application
to pass the ObjC notification about the display connection changing to AppleScript via a hidden ComboBox

  1. Xcode

¢ create a new Objective-C class (Menu File > New File > Objective-C class), name it DisplayCallback
¢ Replace the contents of DisplayCallback.h with

[code]#import <Cocoa/Cocoa.h>

@interface DisplayCallback : NSObject {
IBOutlet NSComboBox *combo;
}

  • (void)setCombo:(NSString *)str;
    @end[/code]
    ¢ Replace the contents of DisplayCallback.m with

[code]#import “DisplayCallback.h”

@implementation DisplayCallback

static void displayReconfigurationCallBack (
CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags,
void *userInfo)
{
if (flags & kCGDisplayAddFlag) {
[(DisplayCallback *)userInfo setCombo:[NSString stringWithFormat:@“%u added”, display]];
}
else if (flags & kCGDisplayRemoveFlag) {
[(DisplayCallback *)userInfo setCombo:[NSString stringWithFormat:@“%u removed”, display]];
}
}

  • (void)awakeFromNib
    {
    NSLog(@“awakeFromNib”);
    CGDisplayRegisterReconfigurationCallback (displayReconfigurationCallBack, self);
    }

  • (void)dealloc
    {
    CGDisplayRemoveReconfigurationCallback (displayReconfigurationCallBack, self);
    [super dealloc];
    }

  • (void)setCombo:(NSString *)str
    {
    [combo removeAllItems];
    [combo insertItemWithObjectValue:str atIndex:0];
    [combo selectItemAtIndex:0];
    }
    @end[/code]

  1. Interface Builder
    ¢ drag an NSObject from the Library into the MainMenu window
    ¢ in Inspector > Identity > Class type DisplayCallback
    ¢ drag a NSComboBox item from the Library into your application window
    ¢ in Inspector > Attributes check Hidden (at the bottom), this item will be invisible
    ¢ in Inspector > AppleScript select your AppleScript in the Script popup menu, name it combo and connect (check) the Event handler Combo Box > selection changed
    ¢ highlight the NSObject, control-drag to the Combo Box, in the appearing menu select combo

Save and Quit Interface Builder

  1. Xcode

¢ in your AppleScript, add this code to the on selection changed handler


on selection changed theObject
    set {displayID, displayAction} to words of (get string value of theObject)
    if displayAction is "added" then
        -- do "added" action
    else if displayAction is "removed" then
        -- do "removed" action
    end if
end selection changed

When you run your application check the log.
If the “awake from nib” message won’t be displayed, open Interface Builder, control-drag from File’s Owner to the new NSObject and choose delegate.
Afterwards you can comment out the NSLog line with

// NSLog(@"awakeFromNib");