mirror of https://github.com/BOINC/boinc.git
Merge pull request #5411 from BOINC/mac_Os14_SS_hotfix
Mac screensaver: update for MacOS 14.0 Sonoma
This commit is contained in:
commit
e08cbf08f7
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2020 University of California
|
||||
// Copyright (C) 2023 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -40,6 +40,7 @@ int startBOINCSaver(void);
|
|||
int getSSMessage(char **theMessage, int* coveredFreq);
|
||||
void windowIsCovered();
|
||||
void drawPreview(CGContextRef myContext);
|
||||
void stopAllGFXApps(void);
|
||||
void closeBOINCSaver(void);
|
||||
void setDefaultDisplayPeriods(void);
|
||||
bool getShow_default_ss_first();
|
||||
|
@ -61,6 +62,8 @@ extern char gUserName[64];
|
|||
extern bool gIsMojave;
|
||||
extern bool gIsCatalina;
|
||||
extern bool gIsHighSierra;
|
||||
extern bool gIsSonoma;
|
||||
extern bool gCant_Use_Shared_Offscreen_Buffer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
@ -164,6 +167,7 @@ public:
|
|||
int getSSMessage(char **theMessage, int* coveredFreq);
|
||||
void windowIsCovered(void);
|
||||
void drawPreview(CGContextRef myContext);
|
||||
void Shared_Offscreen_Buffer_Unavailable(void);
|
||||
void ShutdownSaver();
|
||||
void markAsIncompatible(char *gfxAppName);
|
||||
bool isIncompatible(char *appName);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2020 University of California
|
||||
// Copyright (C) 2023 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -77,6 +77,7 @@ int startBOINCSaver(void);
|
|||
int getSSMessage(char **theMessage, int* coveredFreq);
|
||||
void windowIsCovered();
|
||||
void drawPreview(CGContextRef myContext);
|
||||
void stopAllGFXApps(void);
|
||||
void closeBOINCSaver(void);
|
||||
void setDefaultDisplayPeriods(void);
|
||||
bool getShow_default_ss_first();
|
||||
|
@ -98,6 +99,8 @@ void PrintBacktrace(void);
|
|||
extern bool gIsCatalina;
|
||||
extern bool gIsHighSierra;
|
||||
extern bool gIsMojave;
|
||||
extern bool gIsSonoma;
|
||||
extern bool gCant_Use_Shared_Offscreen_Buffer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2022 University of California
|
||||
// Copyright (C) 2023 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -136,7 +136,6 @@ NSInteger myWindowNumber;
|
|||
NSRect gMovingRect;
|
||||
float gImageXIndent;
|
||||
float gTextBoxHeight;
|
||||
CGFloat gActualTextBoxHeight;
|
||||
NSPoint gCurrentPosition;
|
||||
NSPoint gCurrentDelta;
|
||||
|
||||
|
@ -196,6 +195,10 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
imageView = nil;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (gCant_Use_Shared_Offscreen_Buffer) {
|
||||
stopAllGFXApps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,6 +217,7 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
gIsMojave = (compareOSVersionTo(10, 14) >= 0);
|
||||
gIsCatalina = (compareOSVersionTo(10, 15) >= 0);
|
||||
gIsBigSur = (compareOSVersionTo(11, 0) >= 0);
|
||||
gIsSonoma = (compareOSVersionTo(14, 0) >= 0);
|
||||
|
||||
if (gIsCatalina) {
|
||||
// Under OS 10.15, isPreview is often true even when it shouldn't be
|
||||
|
@ -354,8 +358,6 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
gCurrentDelta.x = 1.0;
|
||||
gCurrentDelta.y = 1.0;
|
||||
|
||||
gActualTextBoxHeight = MINTEXTBOXHEIGHT;
|
||||
|
||||
[ self setAnimationTimeInterval:1/8.0 ];
|
||||
}
|
||||
|
||||
|
@ -447,12 +449,32 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
NSUInteger n;
|
||||
double maxWaitTime;
|
||||
NSRect currentDrawingRect, eraseRect;
|
||||
CGFloat actualTextBoxHeight = MINTEXTBOXHEIGHT;
|
||||
NSPoint imagePosition;
|
||||
char *msg;
|
||||
CFStringRef cf_msg;
|
||||
double timeToBlock, frameStartTime = getDTime();
|
||||
HIThemeTextInfo textInfo;
|
||||
|
||||
NSWindow *myWindow = [ self window ];
|
||||
NSRect windowFrame = [ myWindow frame ];
|
||||
|
||||
if (gIsSonoma) {
|
||||
// Under MacOS 14 Sonoma, screensavers continue to run and "draw" invisibly
|
||||
// after they are dismissed by user activity, to allow them to be used as
|
||||
// wallpaper. Since we don't want the BOINC screensaver to be used as wallpaper,
|
||||
// this would waste system resources.
|
||||
// The only way I've found to determine that the screensaver has been dismissed
|
||||
// by the user is this test of the window level.
|
||||
if ((windowFrame.size.width > 500.) && (windowFrame.size.height > 500.)) {
|
||||
if ([ [ self window ] level ] == 0) {
|
||||
//TODO: more cleanup as in stopAnimation ??
|
||||
closeBOINCSaver();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myIsPreview) {
|
||||
#if 1 // Currently drawRect just draws our logo in the preview window
|
||||
if (gPreview_Image == NULL) {
|
||||
|
@ -474,8 +496,6 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
return;
|
||||
}
|
||||
|
||||
NSWindow *myWindow = [ self window ];
|
||||
|
||||
#if ! DEBUG_UNDER_XCODE
|
||||
// For unkown reasons, OS 10.7 Lion screensaver and later delay several seconds
|
||||
// after user activity before calling stopAnimation, so we check user activity here
|
||||
|
@ -489,7 +509,6 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
}
|
||||
}
|
||||
|
||||
NSRect windowFrame = [ myWindow frame ];
|
||||
if ( (windowFrame.origin.x != 0) || (windowFrame.origin.y != 0) ) {
|
||||
// Hide window on second display to aid in debugging
|
||||
#ifdef _DEBUG
|
||||
|
@ -688,30 +707,18 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
|
||||
if ( (msg != NULL) && (msg[0] != '\0') ) {
|
||||
|
||||
// Set direction of motion to "bounce" off edges of screen
|
||||
if (currentDrawingRect.origin.x <= SAFETYBORDER) {
|
||||
gCurrentDelta.x = (float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.y = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.y)) / 16.;
|
||||
}
|
||||
if ( (currentDrawingRect.origin.x + currentDrawingRect.size.width) >=
|
||||
(viewBounds.origin.x + viewBounds.size.width - SAFETYBORDER) ) {
|
||||
gCurrentDelta.x = -(float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.y = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.y)) / 16.;
|
||||
}
|
||||
if (currentDrawingRect.origin.y + gTextBoxHeight - gActualTextBoxHeight <= SAFETYBORDER) {
|
||||
gCurrentDelta.y = (float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.x = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.x)) / 16.;
|
||||
}
|
||||
if ( (currentDrawingRect.origin.y + currentDrawingRect.size.height) >=
|
||||
(viewBounds.origin.y + viewBounds.size.height - SAFETYBORDER) ) {
|
||||
gCurrentDelta.y = -(float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.x = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.x)) / 16.;
|
||||
}
|
||||
#if 0
|
||||
// For testing
|
||||
gCurrentDelta.x = 0;
|
||||
gCurrentDelta.y = 0;
|
||||
#endif
|
||||
cf_msg = CFStringCreateWithCString(NULL, msg, kCFStringEncodingMacRoman);
|
||||
|
||||
CTFontRef myFont = CTFontCreateWithName(CFSTR("Helvetica"), 20, NULL);
|
||||
HIThemeTextInfo theTextInfo = {kHIThemeTextInfoVersionOne, kThemeStateActive, kThemeSpecifiedFont,
|
||||
kHIThemeTextHorizontalFlushLeft, kHIThemeTextVerticalFlushTop,
|
||||
kHIThemeTextBoxOptionNone, kHIThemeTextTruncationNone, 0, false,
|
||||
0, myFont
|
||||
};
|
||||
textInfo = theTextInfo;
|
||||
|
||||
HIThemeGetTextDimensions(cf_msg, (float)gMovingRect.size.width, &textInfo, NULL, &actualTextBoxHeight, NULL);
|
||||
gTextBoxHeight = actualTextBoxHeight + TEXTBOXTOPBORDER;
|
||||
|
||||
if (!isErased) {
|
||||
[[NSColor blackColor] set];
|
||||
|
@ -751,7 +758,34 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
eraseRect = NSInsetRect(eraseRect, -1, -1);
|
||||
NSRectFill(eraseRect);
|
||||
|
||||
isErased = true;
|
||||
isErased = true;
|
||||
// If text has changed and it now goes below bottom of screen, jump up to show it all.
|
||||
if ((gCurrentPosition.y - gTextBoxHeight) <= SAFETYBORDER) {
|
||||
gCurrentPosition.y = SAFETYBORDER + 1 + gTextBoxHeight;
|
||||
if (gCurrentDelta.y < 0) {
|
||||
gCurrentDelta.y = (float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
}
|
||||
}
|
||||
|
||||
// Set direction of motion to "bounce" off edges of screen
|
||||
if ( (gCurrentDelta.x < 0) && (gCurrentPosition.x <= SAFETYBORDER) ) {
|
||||
gCurrentDelta.x = (float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.y = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.y)) / 16.;
|
||||
}
|
||||
if ( (gCurrentDelta.x > 0) && ( (gCurrentPosition.x + gMovingRect.size.width) >=
|
||||
(viewBounds.origin.x + viewBounds.size.width - SAFETYBORDER) ) ){
|
||||
gCurrentDelta.x = -(float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.y = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.y)) / 16.;
|
||||
}
|
||||
if ( (gCurrentDelta.y < 0) && (gCurrentPosition.y - gTextBoxHeight <= SAFETYBORDER) ) {
|
||||
gCurrentDelta.y = (float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.x = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.x)) / 16.;
|
||||
}
|
||||
if ( (gCurrentDelta.y > 0) && ( (gCurrentPosition.y + gMovingRect.size.height) >=
|
||||
(viewBounds.origin.y + viewBounds.size.height - SAFETYBORDER) ) ) {
|
||||
gCurrentDelta.y = -(float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 16.;
|
||||
gCurrentDelta.x = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.x)) / 16.;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the new drawing area
|
||||
|
@ -762,48 +796,33 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
imagePosition.y = (float) (int)gCurrentPosition.y;
|
||||
|
||||
[ gBOINC_Logo drawAtPoint:imagePosition fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0 ];
|
||||
#if 0
|
||||
// For testing
|
||||
gCurrentDelta.x = 0;
|
||||
gCurrentDelta.y = 0;
|
||||
#endif
|
||||
CGRect bounds = CGRectMake((float) ((int)gCurrentPosition.x),
|
||||
viewBounds.size.height - imagePosition.y + TEXTBOXTOPBORDER,
|
||||
gMovingRect.size.width,
|
||||
MAXTEXTBOXHEIGHT
|
||||
);
|
||||
|
||||
if ( (msg != NULL) && (msg[0] != '\0') ) {
|
||||
cf_msg = CFStringCreateWithCString(NULL, msg, kCFStringEncodingMacRoman);
|
||||
CGContextSaveGState (myContext);
|
||||
CGContextTranslateCTM (myContext, 0, viewBounds.origin.y + viewBounds.size.height);
|
||||
CGContextScaleCTM (myContext, 1.0f, -1.0f);
|
||||
|
||||
CGRect bounds = CGRectMake((float) ((int)gCurrentPosition.x),
|
||||
viewBounds.size.height - imagePosition.y + TEXTBOXTOPBORDER,
|
||||
gMovingRect.size.width,
|
||||
MAXTEXTBOXHEIGHT
|
||||
);
|
||||
CGFloat myWhiteComponents[] = {1.0, 1.0, 1.0, 1.0};
|
||||
CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB ();
|
||||
CGColorRef myTextColor = CGColorCreate(myColorSpace, myWhiteComponents);
|
||||
|
||||
CGContextSaveGState (myContext);
|
||||
CGContextTranslateCTM (myContext, 0, viewBounds.origin.y + viewBounds.size.height);
|
||||
CGContextScaleCTM (myContext, 1.0f, -1.0f);
|
||||
CGContextSetFillColorWithColor(myContext, myTextColor);
|
||||
|
||||
CTFontRef myFont = CTFontCreateWithName(CFSTR("Helvetica"), 20, NULL);
|
||||
HIThemeDrawTextBox(cf_msg, &bounds, &textInfo, myContext, kHIThemeOrientationNormal);
|
||||
|
||||
HIThemeTextInfo theTextInfo = {kHIThemeTextInfoVersionOne, kThemeStateActive, kThemeSpecifiedFont,
|
||||
kHIThemeTextHorizontalFlushLeft, kHIThemeTextVerticalFlushTop,
|
||||
kHIThemeTextBoxOptionNone, kHIThemeTextTruncationNone, 0, false,
|
||||
0, myFont
|
||||
};
|
||||
textInfo = theTextInfo;
|
||||
|
||||
HIThemeGetTextDimensions(cf_msg, (float)gMovingRect.size.width, &textInfo, NULL, &gActualTextBoxHeight, NULL);
|
||||
gActualTextBoxHeight += TEXTBOXTOPBORDER;
|
||||
|
||||
CGFloat myWhiteComponents[] = {1.0, 1.0, 1.0, 1.0};
|
||||
CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB ();
|
||||
CGColorRef myTextColor = CGColorCreate(myColorSpace, myWhiteComponents);
|
||||
|
||||
CGContextSetFillColorWithColor(myContext, myTextColor);
|
||||
|
||||
HIThemeDrawTextBox(cf_msg, &bounds, &textInfo, myContext, kHIThemeOrientationNormal);
|
||||
|
||||
CGColorRelease(myTextColor);
|
||||
CGColorSpaceRelease(myColorSpace);
|
||||
CGContextRestoreGState (myContext);
|
||||
CFRelease(cf_msg);
|
||||
}
|
||||
|
||||
gTextBoxHeight = MAXTEXTBOXHEIGHT + TEXTBOXTOPBORDER;
|
||||
gMovingRect.size.height = [gBOINC_Logo size].height + gTextBoxHeight;
|
||||
CGColorRelease(myTextColor);
|
||||
CGColorSpaceRelease(myColorSpace);
|
||||
CGContextRestoreGState (myContext);
|
||||
CFRelease(cf_msg);
|
||||
|
||||
isErased = false;
|
||||
|
||||
|
@ -813,7 +832,6 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
[[NSColor blackColor] set];
|
||||
isErased = true;
|
||||
NSRectFill(eraseRect);
|
||||
gTextBoxHeight = MAXTEXTBOXHEIGHT;
|
||||
gMovingRect.size.height = [gBOINC_Logo size].height + gTextBoxHeight;
|
||||
}
|
||||
}
|
||||
|
@ -831,7 +849,10 @@ void launchedGfxApp(char * appPath, pid_t thePID, int slot) {
|
|||
// Check for a new graphics app sending us data
|
||||
if (UseSharedOffscreenBuffer() && gfxAppStartTime) {
|
||||
if (mySharedGraphicsController) {
|
||||
[mySharedGraphicsController testConnection];
|
||||
if (!runningSharedGraphics) {
|
||||
// wait for a connection from a gfx app
|
||||
[mySharedGraphicsController testConnection];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1089,10 +1110,17 @@ static bool okToDraw;
|
|||
if (machErr == KERN_SUCCESS) {
|
||||
serverPort = (NSMachPort*)[NSMachPort portWithMachPort:servicePortNum];
|
||||
} else {
|
||||
if (machErr == BOOTSTRAP_NOT_PRIVILEGED) {
|
||||
// As of MacOS 14.0, the legacyScreenSave sandbox prevents using
|
||||
// IOSurfaceLookupFromMachPort. I have filed bug report FB13300491
|
||||
// with Apple and hope they will change this in future MacOS.
|
||||
gCant_Use_Shared_Offscreen_Buffer = true;
|
||||
stopAllGFXApps();
|
||||
}
|
||||
serverPort = MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
if(serverPort != MACH_PORT_NULL)
|
||||
if ((serverPort != MACH_PORT_NULL) && (localPort == MACH_PORT_NULL))
|
||||
{
|
||||
// Create our own local port.
|
||||
localPort = [[NSMachPort alloc] init];
|
||||
|
@ -1132,14 +1160,14 @@ static bool okToDraw;
|
|||
[serverPort invalidate];
|
||||
// [serverPort release];
|
||||
}
|
||||
serverPort = nil;
|
||||
serverPort = MACH_PORT_NULL;
|
||||
[localPort removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
|
||||
|
||||
if ([localPort isValid]) {
|
||||
[localPort invalidate];
|
||||
}
|
||||
// [localPort release];
|
||||
localPort = nil;
|
||||
localPort = MACH_PORT_NULL;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < NUM_IOSURFACE_BUFFERS; i++) {
|
||||
|
@ -1159,13 +1187,14 @@ static bool okToDraw;
|
|||
}
|
||||
}
|
||||
|
||||
if ((serverPort == nil) && (localPort == nil)) {
|
||||
if ((serverPort == MACH_PORT_NULL) && (localPort == MACH_PORT_NULL)) {
|
||||
runningSharedGraphics = false;
|
||||
[openGLView removeFromSuperview]; // Releases openGLView
|
||||
openGLView = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleMachMessage:(void *)msg
|
||||
{
|
||||
union __ReplyUnion___MGCMGSServer_subsystem reply;
|
||||
|
@ -1402,6 +1431,12 @@ static bool UseSharedOffscreenBuffer() {
|
|||
static bool needSharedGfxBuffer = false;
|
||||
|
||||
//return true; // FOR TESTING ONLY
|
||||
// As of MacOS 14.0, the legacyScreenSaver sandbox prevents using
|
||||
// IOSurfaceLookupFromMachPort. I have filed bug report FB13300491
|
||||
// with Apple and hope they will change this in future MacOS.
|
||||
if (gCant_Use_Shared_Offscreen_Buffer) {
|
||||
return false;
|
||||
}
|
||||
if (alreadyTested) {
|
||||
return needSharedGfxBuffer;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2022 University of California
|
||||
// Copyright (C) 2023 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -207,7 +207,13 @@ int main(int argc, char* argv[]) {
|
|||
#endif
|
||||
parentPid = getppid();
|
||||
|
||||
bool cover_gfx_window = (compareOSVersionTo(10, 13) >= 0);
|
||||
// Under MacOS 14.0, the legacyScreenSaver continues to run after the
|
||||
// screensaver is dismissed. Our code elsewhere now kills it, but if
|
||||
// that were to fail this black cover would block the user from
|
||||
// accessing the desktop, so don't use the cover in MacOS 14 for now.
|
||||
|
||||
bool cover_gfx_window = (compareOSVersionTo(10, 13) >= 0) &&
|
||||
(compareOSVersionTo(10, 14) < 0);
|
||||
|
||||
// Create shared app instance
|
||||
[NSApplication sharedApplication];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2022 University of California
|
||||
// Copyright (C) 2023 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -18,9 +18,9 @@
|
|||
// gfx_switcher.C
|
||||
//
|
||||
// Used by screensaver to:
|
||||
// - launch graphics application at given slot number as user & group boinc_project
|
||||
// - launch default graphics application as user & group boinc_project
|
||||
// - kill graphics application with given process ID as user & group boinc_project
|
||||
// - launch graphics application at given slot number
|
||||
// - launch default graphics application
|
||||
// - kill graphics application with given process ID
|
||||
//
|
||||
|
||||
// Special logic used only under OS 10.15 Catalina and later:
|
||||
|
@ -35,11 +35,11 @@
|
|||
// app. This script then launches gfx_switcher, which uses fork and execv to
|
||||
// launch the project graphics app. gfx_switcher writes the graphics app's
|
||||
// process ID to shared memory, to be read by the Screensaver Coordinator.
|
||||
// gfx_switcher waits for the graphics app to exit and notifies then notifies
|
||||
// the Screensaver Coordinator by writing 0 to the shared memory.
|
||||
// gfx_switcher waits for the graphics app to exit and then notifies the
|
||||
// Screensaver Coordinator by writing 0 to the shared memory.
|
||||
//
|
||||
// This Rube Goldberg process is necessary due to limitations on screensavers
|
||||
// introduced in OS 10.15 Catalina.
|
||||
// introduced in OS 10.15 Catalina and OS 14.0 Sonoma.
|
||||
//
|
||||
|
||||
|
||||
|
@ -106,7 +106,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
CFStringRef cf_gUserName = SCDynamicStoreCopyConsoleUser(NULL, NULL, NULL);
|
||||
CFStringGetCString(cf_gUserName, user_name, sizeof(user_name), kCFStringEncodingUTF8);
|
||||
// strlcpy(user_name, getlogin(), sizeof(user_name));
|
||||
// strlcpy(user_name, getenv("USER"), sizeof(user_name));
|
||||
strlcpy(group_name, "boinc_project", sizeof(group_name));
|
||||
|
||||
// Under fast user switching, the BOINC client may be running under a
|
||||
|
@ -319,6 +319,10 @@ void * MonitorScreenSaverEngine(void* param) {
|
|||
print_to_log_file("MonitorScreenSaverEngine: ScreenSaverEngine_Pid=%d", ScreenSaverEngine_Pid);
|
||||
#endif
|
||||
if (ScreenSaverEngine_Pid == 0) {
|
||||
// legacyScreenSaver name under MacOS 14 Sonoma
|
||||
ScreenSaverEngine_Pid = getPidIfRunning("com.apple.ScreenSaver.Engine.legacyScreenSaver");
|
||||
}
|
||||
if (ScreenSaverEngine_Pid == 0) {
|
||||
#ifdef __x86_64__
|
||||
ScreenSaverEngine_Pid = getPidIfRunning("com.apple.ScreenSaver.Engine.legacyScreenSaver.x86_64");
|
||||
#elif defined(__arm64__)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2022 University of California
|
||||
// Copyright (C) 2023 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -106,9 +106,14 @@ static pthread_mutexattr_t saver_mutex_attr;
|
|||
pthread_mutex_t saver_mutex;
|
||||
static char passwd_buf[256];
|
||||
char gUserName[64];
|
||||
bool gIsHighSierra = false; // OS 10.13 or later
|
||||
bool gIsHighSierra = false; // OS 10.13 or later
|
||||
bool gIsMojave = false; // OS 10.14 or later
|
||||
bool gIsCatalina = false; // OS 10.15 or later
|
||||
bool gIsSonoma = false; // OS 14.0 or later
|
||||
|
||||
// As of MacOS 14.0, the legacyScreenSave sandbox
|
||||
// prevents using IOSurfaceLookupFromMachPort.
|
||||
bool gCant_Use_Shared_Offscreen_Buffer = false;
|
||||
|
||||
const char * CantLaunchCCMsg = "Unable to launch BOINC application.";
|
||||
const char * LaunchingCCMsg = "Launching BOINC application.";
|
||||
|
@ -123,6 +128,7 @@ const char * DefaultGFXAppCrashedMsg = "Default screensaver module had an unrec
|
|||
const char * RunningOnBatteryMsg = "Computing and screensaver disabled while running on battery power.";
|
||||
const char * IncompatibleMsg = "Could not connect to screensaver ";
|
||||
const char * CCNotRunningMsg = "BOINC is not running.";
|
||||
const char * NoScreenSaverGraphicsThisMacOS = "BOINC can't show screensaver graphics on this version of MacOS";
|
||||
|
||||
//const char * BOINCExitedSaverMode = "BOINC is no longer in screensaver mode.";
|
||||
|
||||
|
@ -182,6 +188,13 @@ void drawPreview(CGContextRef myContext) {
|
|||
};
|
||||
|
||||
|
||||
void stopAllGFXApps() {
|
||||
if (gspScreensaver) {
|
||||
gspScreensaver->Shared_Offscreen_Buffer_Unavailable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If there are multiple displays, this may get called
|
||||
// multiple times (once for each display), so we need to guard
|
||||
// against any problems that may cause.
|
||||
|
@ -400,7 +413,7 @@ int CScreensaver::Create() {
|
|||
strlcpy(m_gfx_Cleanup_Path, "\"", sizeof(m_gfx_Cleanup_Path));
|
||||
strlcat(m_gfx_Cleanup_Path, m_gfx_Switcher_Path, sizeof(m_gfx_Cleanup_Path));
|
||||
strlcat(m_gfx_Switcher_Path, "/gfx_switcher", sizeof(m_gfx_Switcher_Path));
|
||||
strlcat(m_gfx_Cleanup_Path, "/gfx_cleanup\"", sizeof(m_gfx_Switcher_Path));
|
||||
strlcat(m_gfx_Cleanup_Path, "/gfx_cleanup\"", sizeof(m_gfx_Cleanup_Path));
|
||||
|
||||
// Launch helper app to work around a bug in OS 10.15 Catalina to
|
||||
// kill current graphics app if ScreensaverEngine exits without
|
||||
|
@ -466,6 +479,11 @@ int CScreensaver::getSSMessage(char **theMessage, int* coveredFreq) {
|
|||
return NOTEXTLOGOFREQUENCY;
|
||||
}
|
||||
|
||||
if (gCant_Use_Shared_Offscreen_Buffer) {
|
||||
gspScreensaver->setSSMessageText(NoScreenSaverGraphicsThisMacOS);
|
||||
goto msgIsSet;
|
||||
}
|
||||
|
||||
CheckDualGPUPowerSource();
|
||||
|
||||
switch (saverState) {
|
||||
|
@ -636,6 +654,7 @@ int CScreensaver::getSSMessage(char **theMessage, int* coveredFreq) {
|
|||
}
|
||||
}
|
||||
|
||||
msgIsSet:
|
||||
if (m_MessageText[0]) {
|
||||
newFrequency = TEXTLOGOFREQUENCY;
|
||||
} else {
|
||||
|
@ -657,6 +676,11 @@ void CScreensaver::drawPreview(CGContextRef myContext) {
|
|||
}
|
||||
|
||||
|
||||
void CScreensaver::Shared_Offscreen_Buffer_Unavailable() {
|
||||
DestroyDataManagementThread(); // Kills current GFX app
|
||||
}
|
||||
|
||||
|
||||
void CScreensaver::ShutdownSaver() {
|
||||
DestroyDataManagementThread();
|
||||
|
||||
|
@ -689,6 +713,14 @@ void CScreensaver::ShutdownSaver() {
|
|||
fflush(m_gfx_Cleanup_IPC);
|
||||
pclose(m_gfx_Cleanup_IPC);
|
||||
}
|
||||
|
||||
// Under MacOS 14.0 Sonoma, screensavers continue to run and "draw" invisibly
|
||||
// after they are dismissed by user activity, to allow them to be used as
|
||||
// wallpaper. Since we don't want the BOINC screensaver to be used as wallpaper,
|
||||
// this would waste system resources.
|
||||
if (gIsSonoma) {
|
||||
KillScreenSaver();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1014,9 +1046,8 @@ void print_to_log_file(const char *format, ...) {
|
|||
char buf[256];
|
||||
time_t t;
|
||||
#if USE_SPECIAL_LOG_FILE
|
||||
safe_strcpy(buf, "/Users/");
|
||||
safe_strcat(buf, getlogin());
|
||||
safe_strcat(buf, "/Documents/test_log.txt");
|
||||
safe_strcat(buf, getenv("HOME"));
|
||||
safe_strcat(buf, "/Documents/ss_test_log.txt");
|
||||
FILE *f;
|
||||
f = fopen(buf, "a");
|
||||
if (!f) return;
|
||||
|
|
|
@ -6,3 +6,5 @@
|
|||
(deny file-write* (subpath "/Library/Application Support") )
|
||||
(allow file-write* (subpath "/Library/Application Support/BOINC Data") (subpath "/private/tmp") )
|
||||
(allow file-read* (subpath "/Library/Application Support/BOINC Data") (subpath "/private/tmp") )
|
||||
(allow file-read* (subpath "/private/var/select/sh") )
|
||||
(allow mach-lookup mach-register)
|
||||
|
|
|
@ -1678,19 +1678,27 @@ OSErr UpdateAllVisibleUsers(long brandID, long oldBrandID)
|
|||
}
|
||||
}
|
||||
|
||||
if (! saverAlreadySetForAll) {
|
||||
if (gCommandLineInstall) {
|
||||
err = stat("/tmp/setboincsaver.txt", &sbuf);
|
||||
if (err == noErr) {
|
||||
puts("setboincsaver.txt file detected\n");
|
||||
fflush(stdout);
|
||||
unlink("/tmp/setboincsaver.txt");
|
||||
setSaverForAllUsers = true;
|
||||
}
|
||||
} else {
|
||||
setSaverForAllUsers = ShowMessage(true,
|
||||
// As of MacOS 14.0, the legacyScreenSaver sandbox prevents using
|
||||
// IOSurfaceLookupFromMachPort. I have filed bug report FB13300491
|
||||
// with Apple and hope they will change this in a future MacOS.
|
||||
// Also as of MacOS 14.0 Sonoma, we can't set the screensaver
|
||||
//automatically. I have filed bug report FB13270885 about this.
|
||||
// See a;so the comment at top of SetScreenSaverSelection().
|
||||
if (compareOSVersionTo(14, 0) < 0) {
|
||||
if (! saverAlreadySetForAll) {
|
||||
if (gCommandLineInstall) {
|
||||
err = stat("/tmp/setboincsaver.txt", &sbuf);
|
||||
if (err == noErr) {
|
||||
puts("setboincsaver.txt file detected\n");
|
||||
fflush(stdout);
|
||||
unlink("/tmp/setboincsaver.txt");
|
||||
setSaverForAllUsers = true;
|
||||
}
|
||||
} else {
|
||||
setSaverForAllUsers = ShowMessage(true,
|
||||
(char *)_("Do you want to set %s as the screensaver for all %s users on this Mac?"),
|
||||
brandName[brandID], brandName[brandID]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2008,6 +2016,8 @@ OSErr UpdateAllVisibleUsers(long brandID, long oldBrandID)
|
|||
}
|
||||
|
||||
|
||||
// As of MacOS 14.0 Sonoma, this code no longer will detect the current screensaver,
|
||||
// and will need to be rewritten. See the comment at top of SetScreenSaverSelection().
|
||||
OSErr GetCurrentScreenSaverSelection(passwd *pw, char *moduleName, size_t maxLen) {
|
||||
char buf[1024];
|
||||
FILE *f;
|
||||
|
@ -2047,6 +2057,11 @@ OSErr GetCurrentScreenSaverSelection(passwd *pw, char *moduleName, size_t maxLen
|
|||
}
|
||||
|
||||
|
||||
// As of MacOS 14.0 Sonoma, we can't set the screensaver automatically.
|
||||
// I have filed bug report FB13270885 about this. After this is fixed,
|
||||
// probably need to put an AppleScript to do this in the launch agent
|
||||
// we add for each user. See also:
|
||||
// https://forum.iscreensaver.com/t/understanding-the-macos-sonoma-screensaver-plist/718
|
||||
OSErr SetScreenSaverSelection(char *moduleName, char *modulePath, int type) {
|
||||
OSErr err = noErr;
|
||||
CFStringRef preferenceName = CFSTR("com.apple.screensaver");
|
||||
|
|
Loading…
Reference in New Issue