// macOS-only CoreGraphics display APIs, re-exported alongside iOS CoreGraphics. // One display (FX_DISPLAY_ID) with the phone's landscape size; mode changes are refused. #include #include #include "fx.h" typedef uint32_t CGDirectDisplayID; typedef int32_t CGError; typedef CFDataRef CGDisplayModeRef; // CFType so CFRetain/CFEqual/CFArray callbacks work typedef struct { size_t w, h, pw, ph; double hz; } fx_mode; static fx_mode fx_current_mode(void) { CGSize s = fx_screen_points(); double k = fx_screen_scale(); return (fx_mode){(size_t)s.width, (size_t)s.height, (size_t)(s.width * k), (size_t)(s.height * k), 60.0}; } static const fx_mode *fx_m(CGDisplayModeRef m) { return (const fx_mode *)CFDataGetBytePtr(m); } FX_EXPORT const CFStringRef kCGDisplayShowDuplicateLowResolutionModes = CFSTR("kCGDisplayShowDuplicateLowResolutionModes"); FX_EXPORT CGError CGGetOnlineDisplayList(uint32_t max, CGDirectDisplayID *displays, uint32_t *count) { if (displays && max) displays[0] = FX_DISPLAY_ID; if (count) *count = 1; return 0; } FX_EXPORT CGDirectDisplayID CGMainDisplayID(void) { return FX_DISPLAY_ID; } FX_EXPORT int CGDisplayIsMain(CGDirectDisplayID d) { return d == FX_DISPLAY_ID; } FX_EXPORT CGDirectDisplayID CGDisplayMirrorsDisplay(CGDirectDisplayID d) { return 0; } FX_EXPORT CGRect CGDisplayBounds(CGDirectDisplayID d) { CGSize s = fx_screen_points(); return CGRectMake(0, 0, s.width, s.height); } FX_EXPORT size_t CGDisplayPixelsWide(CGDirectDisplayID d) { return (size_t)fx_screen_points().width; } FX_EXPORT size_t CGDisplayPixelsHigh(CGDirectDisplayID d) { return (size_t)fx_screen_points().height; } FX_EXPORT CGSize CGDisplayScreenSize(CGDirectDisplayID d) { // Physical size in millimetres at ~460 ppi (iPhone 15 Pro class display). double k = fx_render_divisor(); CGSize s = fx_screen_points(); return CGSizeMake(s.width * k / 460.0 * 25.4, s.height * k / 460.0 * 25.4); } FX_EXPORT CGDisplayModeRef CGDisplayCopyDisplayMode(CGDirectDisplayID d) { fx_mode m = fx_current_mode(); return CFDataCreate(NULL, (const UInt8 *)&m, sizeof m); } FX_EXPORT CFArrayRef CGDisplayCopyAllDisplayModes(CGDirectDisplayID d, CFDictionaryRef options) { CGDisplayModeRef m = CGDisplayCopyDisplayMode(d); CFArrayRef a = CFArrayCreate(NULL, (const void **)&m, 1, &kCFTypeArrayCallBacks); CFRelease(m); return a; } FX_EXPORT void CGDisplayModeRelease(CGDisplayModeRef m) { if (m) CFRelease(m); } FX_EXPORT size_t CGDisplayModeGetWidth(CGDisplayModeRef m) { return fx_m(m)->w; } FX_EXPORT size_t CGDisplayModeGetHeight(CGDisplayModeRef m) { return fx_m(m)->h; } FX_EXPORT size_t CGDisplayModeGetPixelWidth(CGDisplayModeRef m) { return fx_m(m)->pw; } FX_EXPORT size_t CGDisplayModeGetPixelHeight(CGDisplayModeRef m) { return fx_m(m)->ph; } FX_EXPORT double CGDisplayModeGetRefreshRate(CGDisplayModeRef m) { return fx_m(m)->hz; } FX_EXPORT uint32_t CGDisplayModeGetIOFlags(CGDisplayModeRef m) { return 0x7; } // valid | safe | default FX_EXPORT int CGDisplayModeIsUsableForDesktopGUI(CGDisplayModeRef m) { return 1; } FX_EXPORT CFStringRef CGDisplayModeCopyPixelEncoding(CGDisplayModeRef m) { return CFStringCreateCopy(NULL, CFSTR("--------RRRRRRRRGGGGGGGGBBBBBBBB")); } FX_EXPORT CGError CGDisplaySetDisplayMode(CGDirectDisplayID d, CGDisplayModeRef m, CFDictionaryRef o) { return 1000; } FX_EXPORT CGError CGDisplayCapture(CGDirectDisplayID d) { return 0; } FX_EXPORT CGError CGCaptureAllDisplays(void) { return 0; } FX_EXPORT CGError CGDisplayRelease(CGDirectDisplayID d) { return 0; } FX_EXPORT CGError CGReleaseAllDisplays(void) { return 0; } FX_EXPORT int32_t CGShieldingWindowLevel(void) { return 2147483630; } FX_EXPORT CGError CGAcquireDisplayFadeReservation(float seconds, uint32_t *token) { if (token) *token = 1; return 0; } FX_EXPORT CGError CGReleaseDisplayFadeReservation(uint32_t token) { return 0; } FX_EXPORT CGError CGDisplayFade(uint32_t token, float d, float a, float b, float r, float g, float bl, int sync) { return 0; } FX_EXPORT uint32_t CGDisplayIDToOpenGLDisplayMask(CGDirectDisplayID d) { return 1; } FX_EXPORT uint32_t CGDisplayIOServicePort(CGDirectDisplayID d) { return 0; } FX_EXPORT CGError CGAssociateMouseAndMouseCursorPosition(int connected) { return 0; } FX_EXPORT CGError CGWarpMouseCursorPosition(CGPoint p) { return 0; } FX_EXPORT CGError CGDisplayMoveCursorToPoint(CGDirectDisplayID d, CGPoint p) { return 0; } FX_EXPORT CGError CGGetDisplayTransferByTable(CGDirectDisplayID d, uint32_t cap, float *r, float *g, float *b, uint32_t *count) { if (count) *count = 0; return 1000; } FX_EXPORT CGError CGSetDisplayTransferByTable(CGDirectDisplayID d, uint32_t n, const float *r, const float *g, const float *b) { return 1000; }