xquartz: support legacy CG APIs as a fallback

This commit is contained in:
Sergey Fedorov 2026-05-25 23:46:07 +08:00 • committed by Enrico Weigelt
commit 83288dedcd
2 changed files with 159 additions and 0 deletions

View file

@ -63,6 +63,155 @@ static Bool ignore_next_fake_mode_update = FALSE;
typedef int (*QuartzModeCallback)
(ScreenPtr, QuartzModeInfoPtr, void *);
/* Modern CG APIs may not work on 10.6 ppc */
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 || defined(__ppc__)
static long
getDictLong(CFDictionaryRef dictRef, CFStringRef key)
{
long value;
CFNumberRef numRef = (CFNumberRef)CFDictionaryGetValue(dictRef, key);
if (!numRef)
return 0;
if (!CFNumberGetValue(numRef, kCFNumberLongType, &value))
return 0;
return value;
}
static double
getDictDouble(CFDictionaryRef dictRef, CFStringRef key)
{
double value;
CFNumberRef numRef = (CFNumberRef)CFDictionaryGetValue(dictRef, key);
if (!numRef)
return 0.0;
if (!CFNumberGetValue(numRef, kCFNumberDoubleType, &value))
return 0.0;
return value;
}
static void
QuartzRandRGetModeInfo(CFDictionaryRef modeRef,
QuartzModeInfoPtr pMode)
{
pMode->width = (size_t)getDictLong(modeRef, kCGDisplayWidth);
pMode->height = (size_t)getDictLong(modeRef, kCGDisplayHeight);
pMode->refresh =
(int)(getDictDouble(modeRef, kCGDisplayRefreshRate) + 0.5);
if (pMode->refresh == 0)
pMode->refresh = DEFAULT_REFRESH;
pMode->ref = NULL;
pMode->pSize = NULL;
}
static Bool
QuartzRandRCopyCurrentModeInfo(CGDirectDisplayID screenId,
QuartzModeInfoPtr pMode)
{
CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId);
if (!curModeRef)
return FALSE;
QuartzRandRGetModeInfo(curModeRef, pMode);
pMode->ref = (void *)curModeRef;
CFRetain(pMode->ref);
return TRUE;
}
static Bool
QuartzRandRSetCGMode(CGDirectDisplayID screenId,
QuartzModeInfoPtr pMode)
{
CFDictionaryRef modeRef = (CFDictionaryRef)pMode->ref;
return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess);
}
static Bool
QuartzRandREnumerateModes(ScreenPtr pScreen,
QuartzModeCallback callback,
void *data)
{
Bool retval = FALSE;
QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
/* Just an 800x600 fallback if we have no attached heads */
if (pQuartzScreen->displayIDs) {
CFDictionaryRef curModeRef, modeRef;
long curBpp;
CFArrayRef modes;
QuartzModeInfo modeInfo;
int i;
CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
curModeRef = CGDisplayCurrentMode(screenId);
if (!curModeRef)
return FALSE;
curBpp = getDictLong(curModeRef, kCGDisplayBitsPerPixel);
modes = CGDisplayAvailableModes(screenId);
if (!modes)
return FALSE;
for (i = 0; i < CFArrayGetCount(modes); i++) {
int cb;
modeRef = (CFDictionaryRef)CFArrayGetValueAtIndex(modes, i);
/* Skip modes that are not usable on the current display or have
a different pixel encoding than the current mode. */
if (((unsigned long)getDictLong(modeRef, kCGDisplayIOFlags) &
kDisplayModeUsableFlags) != kDisplayModeUsableFlags)
continue;
if (getDictLong(modeRef, kCGDisplayBitsPerPixel) != curBpp)
continue;
QuartzRandRGetModeInfo(modeRef, &modeInfo);
modeInfo.ref = (void *)modeRef;
cb = callback(pScreen, &modeInfo, data);
if (cb == CALLBACK_CONTINUE)
retval = TRUE;
else if (cb == CALLBACK_SUCCESS)
return TRUE;
else if (cb == CALLBACK_ERROR)
return FALSE;
}
}
switch (callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
case CALLBACK_SUCCESS:
return TRUE;
case CALLBACK_ERROR:
return FALSE;
case CALLBACK_CONTINUE:
retval = TRUE;
default:
break;
}
switch (callback(pScreen, &pQuartzScreen->fullscreenMode, data)) {
case CALLBACK_SUCCESS:
return TRUE;
case CALLBACK_ERROR:
return FALSE;
case CALLBACK_CONTINUE:
retval = TRUE;
default:
break;
}
return retval;
}
#else /* We have the new CG APIs */
static void
QuartzRandRGetModeInfo(CGDisplayModeRef modeRef,
QuartzModeInfoPtr pMode)
@ -199,6 +348,8 @@ QuartzRandREnumerateModes(ScreenPtr pScreen,
return retval;
}
#endif /* Modern CoreGraphics APIs */
static Bool
QuartzRandRModesEqual(QuartzModeInfoPtr pMode1,
QuartzModeInfoPtr pMode2)

View file

@ -318,6 +318,11 @@ xprAddScreen(int index, ScreenPtr pScreen)
DEBUG_LOG("index=%d depth=%d\n", index, depth);
if (depth == -1) {
/* Modern CG APIs may not work on 10.6 ppc */
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 || defined(__ppc__)
depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) *
CGDisplayBitsPerSample(kCGDirectMainDisplay);
#else
CGDisplayModeRef modeRef;
CFStringRef encStrRef;
@ -347,9 +352,12 @@ xprAddScreen(int index, ScreenPtr pScreen)
}
CFRelease(encStrRef);
#endif
}
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && !defined(__ppc__)
have_depth:
#endif
switch (depth) {
case 8: // pseudo-working
dfb->visuals = PseudoColorMask;