I’m trying to trigger the same thing that the system does when you click on “Detect Displays” in the “Displays” System Preferences pane. Is there a way to do this programmatically? My goal is to create a LaunchAgent that does this at login to reset the display resolution in case a user messes with it.
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
You will need to use a private CoreGraphics routine to get the list of all displays including inactive ones, and then request a rescan of the bus. Try it like this:
#include <IOKit/IOKitLib.h>
#include <IOKit/IOTypes.h>
CGDisplayErr CGSGetDisplayList(CGDisplayCount maxDisplays,
CGDirectDisplayID * onlineDspys,
CGDisplayCount * dspyCnt);
static void DetectDisplays()
{
CGDirectDisplayID displays[8];
CGDisplayCount dspCount = 0;
if (CGSGetDisplayList(8, displays, &dspCount) == noErr)
{
for(int i = 0; i < dspCount; i++)
{
io_service_t service = CGDisplayIOServicePort(displays[i]);
if (service)
IOServiceRequestProbe(service, kIOFBUserRequestProbe);
}
}
}
And link to ApplicationServices and IOKit.
回答2:
Since the CGDisplayIOServicePort
call has been deprecated in OS X 10.9 Mavericks, it may be better to acquire the IOFramebuffer service through an appropriate matching call like so:
void triggerDetectDisplays()
{
// loop over all IOFramebuffer services
CFMutableDictionaryRef matchingDict = IOServiceMatching("IOFramebuffer");
mach_port_t masterPort;
IOMasterPort(MACH_PORT_NULL, &masterPort);
io_iterator_t serviceIterator;
IOServiceGetMatchingServices(masterPort, matchingDict, &serviceIterator);
io_service_t obj = IOIteratorNext(serviceIterator);
while (obj)
{
kern_return_t kr = IOServiceRequestProbe(obj, 0);
obj = IOIteratorNext(serviceIterator);
}
}