54 NSString *modelName = nil;
55 uint32_t displayModelNumber = CGDisplayModelNumber(displayID);
56 NSString *manufacturerName = nil;
57 uint32_t displayVendorNumber = CGDisplayVendorNumber(displayID);
58 NSString *transport = nil;
59 NSString *serialString = nil;
60 uint32_t serialNumber = CGDisplaySerialNumber(displayID);
61 uint8_t manufacturedWeek = 0;
62 uint16_t manufacturedYear = 0;
72 #pragma clang diagnostic push
73 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
74 io_service_t port = CGDisplayIOServicePort(displayID);
75 #pragma clang diagnostic pop
77 NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(port, kIODisplayOnlyPreferredName);
79 NSData *edid = [deviceInfo objectForKey:@kIODisplayEDIDKey];
80 NSString *displayLocation = [deviceInfo objectForKey:@kIODisplayLocationKey];
83 const unsigned char *bytes = (
const unsigned char *)[edid bytes];
85 uint16_t manufacturerId = (bytes[8] << 8) + bytes[9];
87 manufacturerName = [NSString stringWithUTF8String:manufacturer];
90 serialNumber = (bytes[15] << 24) + (bytes[14] << 16) + (bytes[13] << 8) + bytes[12];
92 manufacturedWeek = bytes[16];
93 manufacturedYear = bytes[17] + 1990;
98 if ([displayLocation rangeOfString:
@"SRXDisplayCard" options:0].location != NSNotFound)
99 manufacturerName =
@"Splashtop XDisplay";
100 else if ([displayLocation rangeOfString:
@"info_ennowelbers_proxyframebuffer_fbuffer" options:0].location != NSNotFound)
101 manufacturerName =
@"GoodDual Display";
107 if ([displayLocation rangeOfString:
@"com_yamstu_YamDisplayDriver" options:0].location != NSNotFound)
108 manufacturerName = nil;
111 [deviceInfo autorelease];
112 NSDictionary *localizedNames = [deviceInfo objectForKey:@kDisplayProductName];
113 if ([localizedNames count] > 0)
114 modelName = [localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
118 if (!manufacturerName && !modelName)
124 CFMutableDictionaryRef matching = IOServiceMatching(
"IOMobileFramebuffer");
126 io_iterator_t it = 0;
127 kern_return_t ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &it);
130 while (io_object_t ioo = IOIteratorNext(it))
132 NSDictionary *properties = nil;
133 kern_return_t ret = IORegistryEntryCreateCFProperties(ioo, (CFMutableDictionaryRef *)&properties, NULL, 0);
136 uint32_t ioregSerialNumber = ((NSNumber *)properties[
@"DisplayAttributes"][
@"ProductAttributes"][
@"SerialNumber"]).unsignedLongValue;
137 uint32_t ioregVendorNumber = ((NSNumber *)properties[
@"DisplayAttributes"][
@"ProductAttributes"][
@"LegacyManufacturerID"]).unsignedLongValue;
138 uint32_t ioregModelNumber = ((NSNumber *)properties[
@"DisplayAttributes"][
@"ProductAttributes"][
@"ProductID"]).unsignedLongValue;
139 if (ioregSerialNumber == serialNumber
140 && ioregVendorNumber == displayVendorNumber
141 && ioregModelNumber == displayModelNumber)
143 modelName = [[properties[@"DisplayAttributes"][@"ProductAttributes"][@"ProductName"] retain] autorelease];
144 manufacturerName = [[properties[@"DisplayAttributes"][@"ProductAttributes"][@"ManufacturerID"] retain] autorelease];
145 transport = [[properties[@"Transport"][@"Downstream"] retain] autorelease];
146 serialString = [[properties[@"DisplayAttributes"][@"ProductAttributes"][@"AlphanumericSerialNumber"] retain] autorelease];
147 manufacturedWeek = ((NSNumber *)properties[
@"DisplayAttributes"][
@"ProductAttributes"][
@"WeekOfManufacture"]).unsignedIntValue;
148 manufacturedYear = ((NSNumber *)properties[
@"DisplayAttributes"][
@"ProductAttributes"][
@"YearOfManufacture"]).unsignedIntValue;
151 [properties release];
152 IOObjectRelease(ioo);
160 if (!manufacturerName && !modelName)
162 if (displayVendorNumber == 0x0610
163 || displayVendorNumber ==
'aapl' )
165 manufacturerName =
@"Apple";
166 if (displayModelNumber == 0xa050)
167 modelName =
@"Built-in Liquid Retina XDR Display";
168 else if (displayModelNumber ==
'airp' )
169 modelName =
@"AirPlay";
171 modelName =
@"Display";
173 else if (displayVendorNumber == kDisplayVendorIDUnknown && displayModelNumber ==
'virt' )
174 modelName =
@"Virtual Display";
175 else if (displayVendorNumber == 0x046d && displayModelNumber == 0x100)
176 modelName =
@"Yam Display";
177 else if (displayVendorNumber == 0xf0f0)
178 modelName = [NSString stringWithFormat:@"BetterDummy %d:%d", displayModelNumber / 256 + 1, displayModelNumber % 256 + 1];
184 NSString *name = nil;
185 if (modelName.length > 0)
187 if (manufacturerName.length > 0)
188 name = [NSString stringWithFormat:@"%@: %@", manufacturerName, modelName];
193 if (name.length == 0)
195 if (manufacturerName)
196 name = manufacturerName;
207 name = [NSString stringWithFormat:@"Unknown display (vendor 0x%04x, model 0x%04x)", displayVendorNumber, displayModelNumber];
212 NSMutableArray *parentheticalComponents = [NSMutableArray new];
214 if (transport.length > 0)
215 [parentheticalComponents addObject:transport];
217 if (serialString.length > 0)
218 [parentheticalComponents addObject:serialString];
219 else if (serialNumber)
220 [parentheticalComponents addObject:[NSString stringWithFormat:@"%u", serialNumber]];
222 if (manufacturedYear)
223 [parentheticalComponents addObject:[NSString stringWithFormat:@"%d-W%02d", manufacturedYear, manufacturedWeek]];
226 NSString *compositeName = name;
227 NSString *parenthetical = [parentheticalComponents componentsJoinedByString:@", "];
228 [parentheticalComponents release];
229 if (parenthetical.length > 0)
230 compositeName = [name stringByAppendingFormat:@" (%@)", parenthetical];
234#pragma clang diagnostic push
235#pragma clang diagnostic ignored "-Wdeprecated-declarations"
236 io_service_t port = CGDisplayIOServicePort(displayID);
237 bool captured = CGDisplayIsCaptured(displayID);
238#pragma clang diagnostic pop
240 CGGammaValue r0 = 0, r1 = 0, rg = 0, g0 = 0, g1 = 0, gg = 0, b0 = 0, b1 = 0, bg = 0;
241 CGGetDisplayTransferByFormula(displayID, &r0, &r1, &rg, &g0, &g1, &gg, &b0, &b1, &bg);
243 uint32_t gammaCap = CGDisplayGammaTableCapacity(displayID);
244 CGGammaValue *gamma = (CGGammaValue *)malloc(
sizeof(CGGammaValue) * gammaCap * 3);
245 uint32_t gammaCount = 0;
246 CGGetDisplayTransferByTable(displayID, gammaCap, gamma, gamma + gammaCap, gamma + gammaCap * 2, &gammaCount);
248 VUserLog(
"[%-55s] %5zux%-5zu (%4.0fx%-4.0f mm) @ %5gx%-5g id=%02x port=%x vendor=0x%08x (%10u) model=0x%08x (%10u) serial=0x%08x (%10u) unit=0x%04x (%5u) active=%d asleep=%d online=%d main=%d builtin=%d mirror=%s%s gl=%d stereo=%d captured=%d shield=%x rotation=%g cgcontext=%p transfer=r(%g %g %g %7.5f) g(%g %g %g %7.5f) b(%g %g %g %7.5f)",
249 compositeName.UTF8String,
250 CGDisplayPixelsWide(displayID),
251 CGDisplayPixelsHigh(displayID),
252 CGDisplayScreenSize(displayID).width,
253 CGDisplayScreenSize(displayID).height,
254 CGDisplayBounds(displayID).origin.x,
255 CGDisplayBounds(displayID).origin.y,
258 displayVendorNumber, displayVendorNumber,
259 displayModelNumber, displayModelNumber,
260 serialNumber, serialNumber,
261 CGDisplayUnitNumber(displayID), CGDisplayUnitNumber(displayID),
262 CGDisplayIsActive(displayID),
263 CGDisplayIsAsleep(displayID),
264 CGDisplayIsOnline(displayID),
265 CGDisplayIsMain(displayID),
266 CGDisplayIsBuiltin(displayID),
267 CGDisplayIsInMirrorSet(displayID) ? (CGDisplayIsAlwaysInMirrorSet(displayID) ?
"always" :
"yes") :
"no",
268 CGDisplayIsInHWMirrorSet(displayID) ?
" hw" :
"",
269 CGDisplayUsesOpenGLAcceleration(displayID),
270 CGDisplayIsStereo(displayID),
272 CGShieldingWindowID(displayID),
273 CGDisplayRotation(displayID),
274 CGDisplayGetDrawingContext(displayID),
275 r0, r1, rg, gamma[1],
276 g0, g1, gg, gamma[1 + gammaCap],
277 b0, b1, bg, gamma[1 + gammaCap * 2]);
436 if (flags == kCGDisplayBeginConfigurationFlag)
443 vector<string> flagDescriptions;
444 if (flags & kCGDisplayMovedFlag) flagDescriptions.push_back(
"moved");
445 if (flags & kCGDisplaySetMainFlag) flagDescriptions.push_back(
"set main");
446 if (flags & kCGDisplaySetModeFlag) flagDescriptions.push_back(
"set mode");
447 if (flags & kCGDisplayAddFlag) flagDescriptions.push_back(
"added");
448 if (flags & kCGDisplayRemoveFlag) flagDescriptions.push_back(
"removed");
449 if (flags & kCGDisplayEnabledFlag) flagDescriptions.push_back(
"enabled");
450 if (flags & kCGDisplayDisabledFlag) flagDescriptions.push_back(
"disabled");
451 if (flags & kCGDisplayMirrorFlag) flagDescriptions.push_back(
"mirrored");
452 if (flags & kCGDisplayUnMirrorFlag) flagDescriptions.push_back(
"unmirrored");
453 if (flags & kCGDisplayDesktopShapeChangedFlag) flagDescriptions.push_back(
"desktop shape changed");
454 stringstream flagDescription;
455 for_each(flagDescriptions.begin(), flagDescriptions.end(), [&flagDescription] (
const string &s) {
456 if (flagDescription.tellp())
457 flagDescription <<
", ";
458 flagDescription << s;
465 for (
unsigned long i = 0; i < screenCount; ++i)
466 if (screens[i].
id == display)
467 VUserLog(
"Display \"%s\": %s", screens[i].name, flagDescription.str().c_str());
471 const double notificationDelaySeconds = 0.25;
472 static dispatch_source_t timer = 0;
475 dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, notificationDelaySeconds*NSEC_PER_SEC), DISPATCH_TIME_FOREVER, notificationDelaySeconds*NSEC_PER_SEC/10);
478 timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
479 dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, notificationDelaySeconds*NSEC_PER_SEC), DISPATCH_TIME_FOREVER, notificationDelaySeconds*NSEC_PER_SEC/10);
480 dispatch_source_set_event_handler(timer, ^{
482 dispatch_source_cancel(timer);
484 dispatch_source_set_cancel_handler(timer, ^{
485 dispatch_release(timer);
488 dispatch_resume(timer);