#import #import #import #include #include // https://github.com/codebytere/node-mac-permissions/blob/main/permissions.mm extern "C" bool InputMonitoringAuthStatus(bool prompt) { if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_15) { IOHIDAccessType theType = IOHIDCheckAccess(kIOHIDRequestTypeListenEvent); NSLog(@"IOHIDCheckAccess = %d, kIOHIDAccessTypeGranted = %d", theType, kIOHIDAccessTypeGranted); switch (theType) { case kIOHIDAccessTypeGranted: return true; break; case kIOHIDAccessTypeDenied: { if (prompt) { NSString *urlString = @"x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent"; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]]; } break; } case kIOHIDAccessTypeUnknown: { if (prompt) { bool result = IOHIDRequestAccess(kIOHIDRequestTypeListenEvent); NSLog(@"IOHIDRequestAccess result = %d", result); } break; } default: break; } } else { return true; } return false; } extern "C" bool MacCheckAdminAuthorization() { AuthorizationRef authRef; OSStatus status; status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef); if (status != errAuthorizationSuccess) { printf("Failed to create AuthorizationRef\n"); return false; } AuthorizationItem authItem = {kAuthorizationRightExecute, 0, NULL, 0}; AuthorizationRights authRights = {1, &authItem}; AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; status = AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL); if (status != errAuthorizationSuccess) { printf("Failed to authorize\n"); return false; } AuthorizationFree(authRef, kAuthorizationFlagDefaults); return true; } extern "C" float BackingScaleFactor() { NSScreen* s = [NSScreen mainScreen]; if (s) return [s backingScaleFactor]; return 1; } // https://github.com/jhford/screenresolution/blob/master/cg_utils.c // https://github.com/jdoupe/screenres/blob/master/setgetscreen.m size_t bitDepth(CGDisplayModeRef mode) { size_t depth = 0; // Deprecated, same display same bpp? // https://stackoverflow.com/questions/8210824/how-to-avoid-cgdisplaymodecopypixelencoding-to-get-bpp // https://github.com/libsdl-org/SDL/pull/6628 CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels // are made up and possibly non-sensical if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { depth = 96; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 64; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { depth = 48; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 32; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 30; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 16; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { depth = 8; } CFRelease(pixelEncoding); return depth; } extern "C" bool MacGetModeNum(CGDirectDisplayID display, uint32_t *numModes) { CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { return false; } *numModes = CFArrayGetCount(allModes); CFRelease(allModes); return true; } extern "C" bool MacGetModes(CGDirectDisplayID display, uint32_t *widths, uint32_t *heights, uint32_t max, uint32_t *numModes) { CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display); if (currentMode == NULL) { return false; } CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { CGDisplayModeRelease(currentMode); return false; } uint32_t allModeCount = CFArrayGetCount(allModes); uint32_t realNum = 0; for (uint32_t i = 0; i < allModeCount && realNum < max; i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if (CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && bitDepth(currentMode) == bitDepth(mode)) { widths[realNum] = (uint32_t)CGDisplayModeGetWidth(mode); heights[realNum] = (uint32_t)CGDisplayModeGetHeight(mode); realNum++; } } *numModes = realNum; CGDisplayModeRelease(currentMode); CFRelease(allModes); return true; } extern "C" bool MacGetMode(CGDirectDisplayID display, uint32_t *width, uint32_t *height) { CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display); if (mode == NULL) { return false; } *width = (uint32_t)CGDisplayModeGetWidth(mode); *height = (uint32_t)CGDisplayModeGetHeight(mode); CGDisplayModeRelease(mode); return true; } static bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { CGError rc; CGDisplayConfigRef config; rc = CGBeginDisplayConfiguration(&config); if (rc != kCGErrorSuccess) { return false; } rc = CGConfigureDisplayWithDisplayMode(config, display, mode, NULL); if (rc != kCGErrorSuccess) { return false; } rc = CGCompleteDisplayConfiguration(config, kCGConfigureForSession); if (rc != kCGErrorSuccess) { return false; } return true; } extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t height) { bool ret = false; CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display); if (currentMode == NULL) { return ret; } CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { CGDisplayModeRelease(currentMode); return ret; } int numModes = CFArrayGetCount(allModes); for (int i = 0; i < numModes; i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if (width == CGDisplayModeGetWidth(mode) && height == CGDisplayModeGetHeight(mode) && CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && bitDepth(currentMode) == bitDepth(mode)) { ret = setDisplayToMode(display, mode); break; } } CGDisplayModeRelease(currentMode); CFRelease(allModes); return ret; }