XQuartz: RandR: Don't crash if X11 is launched while there are no attached displays

If CG reports no displays when launching, we could crash in RandR.  Instead, just
provide a fake 800x600 display until we are notified about displays being attached.

Signed-off-by: Jeremy Huddleston <jeremyhu@apple.com>
This commit is contained in:
Jeremy Huddleston 2011-05-22 09:32:57 -07:00
parent f25ca898c5
commit 60af79e35e
3 changed files with 116 additions and 99 deletions

View File

@ -464,11 +464,15 @@ void QuartzSpaceChanged(uint32_t space_id) {
void QuartzCopyDisplayIDs(ScreenPtr pScreen,
int displayCount, CGDirectDisplayID *displayIDs) {
QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
int size = displayCount * sizeof(CGDirectDisplayID);
free(pQuartzScreen->displayIDs);
if(displayCount) {
size_t size = displayCount * sizeof(CGDirectDisplayID);
pQuartzScreen->displayIDs = malloc(size);
memcpy(pQuartzScreen->displayIDs, displayIDs, size);
} else {
pQuartzScreen->displayIDs = NULL;
}
pQuartzScreen->displayCount = displayCount;
}

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons,
* 2010 Jan Hauffa.
* 2010 Apple Inc.
* 2010-2011 Apple Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@ -124,13 +124,16 @@ static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
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;
BOOL retval = FALSE;
QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
curModeRef = CGDisplayCurrentMode(screenId);
@ -163,6 +166,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
else if (cb == CALLBACK_ERROR)
return FALSE;
}
}
switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
case CALLBACK_SUCCESS:
@ -225,15 +229,17 @@ static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
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) {
CGDisplayModeRef curModeRef, modeRef;
CFStringRef curPixelEnc, pixelEnc;
CFComparisonResult pixelEncEqual;
CFArrayRef modes;
QuartzModeInfo modeInfo;
int i;
Bool retval = FALSE;
QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
curModeRef = CGDisplayCopyDisplayMode(screenId);
@ -280,6 +286,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
CFRelease(modes);
CFRelease(curPixelEnc);
}
switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
case CALLBACK_SUCCESS:
@ -347,9 +354,13 @@ static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL doRegister) {
QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
Bool captureDisplay = (pMode->refresh != FAKE_REFRESH_FULLSCREEN && pMode->refresh != FAKE_REFRESH_ROOTLESS);
CGDirectDisplayID screenId;
if(pQuartzScreen->displayIDs == NULL)
return FALSE;
screenId = pQuartzScreen->displayIDs[0];
if(XQuartzShieldingWindowLevel == 0 && captureDisplay) {
if(!X11ApplicationCanEnterRandR())
return FALSE;
@ -379,6 +390,7 @@ static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL
if(pQuartzScreen->currentMode.ref)
CFRelease(pQuartzScreen->currentMode.ref);
pQuartzScreen->currentMode = *pMode;
if(pQuartzScreen->currentMode.ref)
CFRetain(pQuartzScreen->currentMode.ref);
if(XQuartzShieldingWindowLevel != 0 && !captureDisplay) {
@ -406,13 +418,8 @@ static int QuartzRandRSetModeCallback (ScreenPtr pScreen,
}
static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
*rotations = RR_Rotate_0; /* TODO: support rotation */
if (pQuartzScreen->displayCount == 0)
return FALSE;
return QuartzRandREnumerateModes(pScreen, QuartzRandRRegisterModeCallback, NULL);
}
@ -427,9 +434,6 @@ static Bool QuartzRandRSetConfig (ScreenPtr pScreen,
reqMode.height = pSize->height;
reqMode.refresh = rate;
if (pQuartzScreen->displayCount == 0)
return FALSE;
/* Do not switch modes if requested mode is equal to current mode. */
if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode))
return TRUE;
@ -446,17 +450,24 @@ static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) {
QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
QuartzModeInfo activeMode;
if (!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0], &activeMode)) {
if(pQuartzScreen->displayCount > 0) {
if(!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0], &activeMode)) {
ErrorF("Unable to determine current display mode.\n");
return FALSE;
}
} else {
memset(&activeMode, 0, sizeof(activeMode));
activeMode.width = 800;
activeMode.height = 600;
activeMode.refresh = 60;
}
if(pQuartzScreen->fullscreenMode.ref)
CFRelease(pQuartzScreen->fullscreenMode.ref);
if(pQuartzScreen->currentMode.ref)
CFRelease(pQuartzScreen->currentMode.ref);
if (pQuartzScreen->displayCount > 1) {
if(pQuartzScreen->displayCount > 1) {
activeMode.width = pScreen->width;
activeMode.height = pScreen->height;
if(XQuartzIsRootless)
@ -479,6 +490,7 @@ static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) {
/* This extra retain is for currentMode's copy.
* fullscreen and rootless share a retain.
*/
if(pQuartzScreen->currentMode.ref)
CFRetain(pQuartzScreen->currentMode.ref);
DEBUG_LOG("rootlessMode: %d x %d\n", (int)pQuartzScreen->rootlessMode.width, (int)pQuartzScreen->rootlessMode.height);

View File

@ -193,6 +193,7 @@ xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height, ScreenPtr pScr
*width = 800;
*height = 600;
PseudoramiXAddScreen(*x, *y, *width, *height);
QuartzCopyDisplayIDs(pScreen, 0, NULL);
return;
}