From 560ae25d557574b369d30d815c3205a3cbaf4cdd Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Thu, 14 Feb 2008 12:26:13 +0000 Subject: [PATCH] New Mac screensaver uses Quartz APIs, not deprecated QuickDraw, works more like Windows saver. svn path=/trunk/boinc/; revision=14743 --- checkin_notes | 18 +- clientscr/Mac_Saver_Module.h | 9 +- clientscr/Mac_Saver_ModuleView.h | 2 +- clientscr/Mac_Saver_ModuleView.m | 304 +++++++++++++++++----- clientscr/mac_saver_module.cpp | 56 ++-- clientscr/res/boinc_ss_logo.png | Bin 0 -> 12340 bytes clientscr/res/gridrepublic_ss_logo.png | Bin 0 -> 7697 bytes mac_build/boinc.xcodeproj/project.pbxproj | 6 + 8 files changed, 292 insertions(+), 103 deletions(-) create mode 100644 clientscr/res/boinc_ss_logo.png create mode 100644 clientscr/res/gridrepublic_ss_logo.png diff --git a/checkin_notes b/checkin_notes index 8b0231cbda..0f55b778e2 100644 --- a/checkin_notes +++ b/checkin_notes @@ -1269,7 +1269,7 @@ Rom Feb 7 2008 log_flags.C, .h Charlie Feb 7 2008 - - MGR: If use shuts down connected client, don't auto-relaunch it. + - MGR: If user shuts down connected client, don't auto-relaunch it. clientgui/ MainDocument.cpp,h @@ -1380,3 +1380,19 @@ David Feb 13 2008 create_account_action.php create_account_form.php login_form.php + +Charlie Feb 14 2008 + - MAC SCR: Use Quartz drawing instead of deprecated QuickDraw APIs. + Show moving logo with text underneath like Windows screensaver + instead of horizontally scrolling banner text. + + clientscr/ + mac_saver_module.cpp,h + Mac_Saver_Module.h + screensaver.cpp + res/ + boinc_ss_logo.png (new) + gridrepublic_ss_logo.png (new) + mac_build/ + boinc.xcodeproj/ + project.pbxproj diff --git a/clientscr/Mac_Saver_Module.h b/clientscr/Mac_Saver_Module.h index d3ab402780..ae4fb46e5a 100644 --- a/clientscr/Mac_Saver_Module.h +++ b/clientscr/Mac_Saver_Module.h @@ -33,9 +33,11 @@ extern "C" { #endif int initBOINCSaver(Boolean ispreview); -int drawGraphics(GrafPtr aPort); +int drawGraphics(char **theMessage); void drawPreview(GrafPtr aPort); void closeBOINCSaver(void); +void print_to_log_file(const char *format, ...); +void strip_cr(char *buf); #ifdef __cplusplus } // extern "C" @@ -69,7 +71,6 @@ protected: void setBannerText(const char *msg, GrafPtr aPort); void updateBannerText(char *msg, GrafPtr aPort); void drawBanner(GrafPtr aPort); - void print_to_log_file(const char *format, ...); void strip_cr(char *buf); char m_gfx_Switcher_Path[MAXPATHLEN]; bool m_bErrorMode; // Whether to display an error @@ -129,10 +130,10 @@ protected: char m_MsgBuf[2048]; char m_BannerText[2048]; int m_BannerWidth; - StringPtr m_CurrentBannerMessage; + char* m_CurrentBannerMessage; char* m_BrandText; public: - int drawGraphics(GrafPtr aPort); + int drawGraphics(char **theMessage); void drawPreview(GrafPtr aPort); void ShutdownSaver(); diff --git a/clientscr/Mac_Saver_ModuleView.h b/clientscr/Mac_Saver_ModuleView.h index 1ef029d08c..7b30380035 100644 --- a/clientscr/Mac_Saver_ModuleView.h +++ b/clientscr/Mac_Saver_ModuleView.h @@ -45,7 +45,7 @@ void setFrame(Rect *frame); int initBOINCSaver(Boolean ispreview); -int drawGraphics(GrafPtr aPort); +int drawGraphics(char **theMessage); void drawPreview(GrafPtr aPort); void closeBOINCSaver(void); void displayText(const unsigned char *s, GrafPtr aPort); diff --git a/clientscr/Mac_Saver_ModuleView.m b/clientscr/Mac_Saver_ModuleView.m index c094d684d9..d4be13a6d6 100644 --- a/clientscr/Mac_Saver_ModuleView.m +++ b/clientscr/Mac_Saver_ModuleView.m @@ -23,66 +23,123 @@ // #import "Mac_Saver_ModuleView.h" +#include + +void print_to_log_file(const char *format, ...); +void strip_cr(char *buf); int gGoToBlank; // True if we are to blank the screen int gBlankingTime; // Delay in minutes before blanking the screen NSString *gPathToBundleResources; +NSImage *gBOINC_Logo; + +NSRect gMovingRect; +float gImageXIndent; +float gTextBoxHeight; +NSPoint gCurrentPosition; +NSPoint gCurrentDelta; + +ATSUStyle theStyle; +ATSUFontID theFontID; +Fixed atsuSize; +char myFontName[] = "Helvetica"; +//char myFontName[] = "Lucida Blackletter"; + +ATSUAttributeTag theTags[] = { kATSUFontTag, kATSUSizeTag }; +ByteCount theSizes[] = { sizeof (ATSUFontID), sizeof(Fixed) }; +ATSUAttributeValuePtr theValues[] = { &theFontID, &atsuSize }; + +CGContextRef myContext; +bool isErased; + +#define TEXTBOXMINWIDTH 400.0 +#define MINTEXTBOXHEIGHT 40.0 +#define MAXTEXTBOXHEIGHT 300.0 +#define TEXTBOXTOPBORDER 10 +#define SAFETYBORDER 20.0 +#define MINDELTA 8 +#define MAXDELTA 20 + +int signof(float x) { + return (x > 0.0 ? 1 : -1); +} @implementation BOINC_Saver_ModuleView - (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview { - NSQuickDrawView * myQDView; NSBundle * myBundle; + OSStatus err; self = [ super initWithFrame:frame isPreview:isPreview ]; - if (self) { - myBundle = [ NSBundle bundleForClass:[self class]]; - // grab the screensaver defaults - mBundleID = [ myBundle bundleIdentifier ]; + if (gBOINC_Logo == NULL) { + if (self) { + myBundle = [ NSBundle bundleForClass:[self class]]; + // grab the screensaver defaults + mBundleID = [ myBundle bundleIdentifier ]; - // Path to our copy of switcher utility application in this screensaver bundle - gPathToBundleResources = [ myBundle resourcePath ]; - - ScreenSaverDefaults *defaults = [ ScreenSaverDefaults defaultsForModuleWithName:mBundleID ]; - - // try to load the version key, used to see if we have any saved settings - mVersion = [defaults floatForKey:@"version"]; - if (!mVersion) { - // no previous settings so define our defaults - mVersion = 1; - gGoToBlank = NO; - gBlankingTime = 1; + // Path to our copy of switcher utility application in this screensaver bundle + gPathToBundleResources = [ myBundle resourcePath ]; - // write out the defaults - [ defaults setInteger:mVersion forKey:@"version" ]; - [ defaults setInteger:gGoToBlank forKey:@"GoToBlank" ]; - [ defaults setInteger:gBlankingTime forKey:@"BlankingTime" ]; + ScreenSaverDefaults *defaults = [ ScreenSaverDefaults defaultsForModuleWithName:mBundleID ]; - // synchronize - [defaults synchronize]; + // try to load the version key, used to see if we have any saved settings + mVersion = [defaults floatForKey:@"version"]; + if (!mVersion) { + // no previous settings so define our defaults + mVersion = 1; + gGoToBlank = NO; + gBlankingTime = 1; + + // write out the defaults + [ defaults setInteger:mVersion forKey:@"version" ]; + [ defaults setInteger:gGoToBlank forKey:@"GoToBlank" ]; + [ defaults setInteger:gBlankingTime forKey:@"BlankingTime" ]; + + // synchronize + [defaults synchronize]; + } + + // set defaults... + gGoToBlank = [ defaults integerForKey:@"GoToBlank" ]; + gBlankingTime = [ defaults integerForKey:@"BlankingTime" ]; + + [ self setAutoresizesSubviews:YES ]; // make sure the subview resizes. + + NSString *fileName = [[ NSBundle bundleForClass:[ self class ]] pathForImageResource:@"boinc_ss_logo" ]; + if (! fileName) { + // What should we do in this case? + return self; + } + + gBOINC_Logo = [[ NSImage alloc ] initWithContentsOfFile:fileName ]; + gMovingRect.origin.x = 0.0; + gMovingRect.origin.y = 0.0; + gMovingRect.size = [gBOINC_Logo size]; + + if (gMovingRect.size.width < TEXTBOXMINWIDTH) { + gImageXIndent = (TEXTBOXMINWIDTH - gMovingRect.size.width) / 2; + gMovingRect.size.width = TEXTBOXMINWIDTH; + } else { + gImageXIndent = 0.0; + } + gTextBoxHeight = MINTEXTBOXHEIGHT; + gMovingRect.size.height += gTextBoxHeight; + gCurrentPosition.x = SAFETYBORDER + 1; + gCurrentPosition.y = SAFETYBORDER + 1 + gTextBoxHeight; + gCurrentDelta.x = 1.0; + gCurrentDelta.y = 1.0; + + [ self setAnimationTimeInterval:1/8.0 ]; + + ATSUFindFontFromName(myFontName, strlen(myFontName), kFontFamilyName, kFontMacintoshPlatform, + kFontNoScriptCode, kFontNoLanguageCode, &theFontID); + + err = ATSUCreateStyle(&theStyle); + atsuSize = Long2Fix (24); + err = ATSUSetAttributes(theStyle, 2, theTags, theSizes, theValues); } - - // set defaults... - gGoToBlank = [ defaults integerForKey:@"GoToBlank" ]; - gBlankingTime = [ defaults integerForKey:@"BlankingTime" ]; - - myQDView = [[ NSQuickDrawView alloc ] initWithFrame:frame ]; - if (!myQDView) { - [ self autorelease ]; - return nil; - } - - [ self setAutoresizesSubviews:YES ]; // make sure the subview resizes. - [ self addSubview:myQDView ]; - [ myQDView release ]; - if (isPreview) - previewQDView = myQDView; - else - mainQDView = myQDView; - - [ self setAnimationTimeInterval:1/8.0 ]; } - + return self; } @@ -115,12 +172,17 @@ NSString *gPathToBundleResources; } - (void)animateOneFrame { - int newFrequency; + int newFrequency = 0; NSRect theFrame = [ self frame ]; - Point p = { 0, 0 }; + NSRect currentDrawingRect, eraseRect; + NSPoint imagePosition; + Rect r; + char *msg; + CFStringRef cf_msg; AbsoluteTime timeToUnblock, frameStartTime = UpTime(); + OSStatus err; - if ([ self isPreview ]) { + if ([ self isPreview ]) { #if 1 // Currently drawRect just draws our logo in the preview window NSString *fileName = [[ NSBundle bundleForClass:[ self class ]] pathForImageResource:@"boinc" ]; if (fileName) { @@ -132,36 +194,147 @@ NSString *gPathToBundleResources; } [ self setAnimationTimeInterval:1/1.0 ]; #else // Code for possible future use if we want to draw more in preview - [ previewQDView lockFocus ]; - drawPreview([ previewQDView qdPort ]); - [ previewQDView unlockFocus ]; - QDFlushPortBuffer([ previewQDView qdPort ], nil); + myContext = [[NSGraphicsContext currentContext] graphicsPort]; + drawPreview(myContext); [ self setAnimationTimeInterval:1/30.0 ]; #endif return; } - - [ mainQDView lockFocus ]; - LocalToGlobal(&p); - if ((p.h != 0) || (p.v != 0)) { - [ mainQDView unlockFocus ]; - + + myContext = [[NSGraphicsContext currentContext] graphicsPort]; +// [myContext retain]; + + NSWindow *myWindow = [ self window ]; + NSRect windowFrame = [ myWindow frame ]; + if ( (windowFrame.origin.x != 0) || (windowFrame.origin.y != 0) ) { // Hide window on second display to aid in debugging -// [[[ NSView focusView] window ] setLevel:kCGMinimumWindowLevel ]; + [[[ NSView focusView] window ] setLevel:kCGMinimumWindowLevel ]; return; // We draw only to main screen } + + NSRect viewBounds = [self bounds]; + + newFrequency = drawGraphics(&msg); + + // Clear the previous drawing area + currentDrawingRect = gMovingRect; + currentDrawingRect.origin.x = (float) ((int)gCurrentPosition.x); + currentDrawingRect.origin.y += (float) ((int)gCurrentPosition.y - gTextBoxHeight); + + 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) / 8.; + gCurrentDelta.y = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.y)) / 8.; + } + if ( (currentDrawingRect.origin.x + currentDrawingRect.size.width) >= + (viewBounds.origin.x + viewBounds.size.width - SAFETYBORDER) ) { + gCurrentDelta.x = -(float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 8.; + gCurrentDelta.y = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.y)) / 8.; + } + if (currentDrawingRect.origin.y <= SAFETYBORDER) { + gCurrentDelta.y = (float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 8.; + gCurrentDelta.x = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.x)) / 8.; + } + if ( (currentDrawingRect.origin.y + currentDrawingRect.size.height) >= + (viewBounds.origin.y + viewBounds.size.height - SAFETYBORDER) ) { + gCurrentDelta.y = -(float)SSRandomIntBetween(MINDELTA, MAXDELTA) / 8.; + gCurrentDelta.x = (float)(SSRandomIntBetween(MINDELTA, MAXDELTA) * signof(gCurrentDelta.x)) / 8.; + } + +#if 0 + // For testing + gCurrentDelta.x = 0; + gCurrentDelta.y = 0; +#endif + + if (!isErased) { + [[NSColor blackColor] set]; + + imagePosition.x = (float) ((int)gCurrentPosition.x + gImageXIndent); + imagePosition.y = (float) (int)gCurrentPosition.y; + eraseRect.origin.y = imagePosition.y; + eraseRect.size.height = currentDrawingRect.size.height - gTextBoxHeight; + + if (gCurrentDelta.x > 0) { + eraseRect.origin.x = imagePosition.x - 1; + eraseRect.size.width = gCurrentDelta.x + 1; + } else { + eraseRect.origin.x = currentDrawingRect.origin.x + currentDrawingRect.size.width - gImageXIndent + gCurrentDelta.x - 1; + eraseRect.size.width = -gCurrentDelta.x + 1; + } + + eraseRect = NSInsetRect(eraseRect, -1, -1); + NSRectFill(eraseRect); + + eraseRect.origin.x = imagePosition.x; + eraseRect.size.width = currentDrawingRect.size.width - gImageXIndent - gImageXIndent; + + if (gCurrentDelta.y > 0) { + eraseRect.origin.y = imagePosition.y; + eraseRect.size.height = gCurrentDelta.y + 1; + } else { + eraseRect.origin.y = imagePosition.y + currentDrawingRect.size.height - gTextBoxHeight - 1; + eraseRect.size.height = -gCurrentDelta.y + 1; + } + eraseRect = NSInsetRect(eraseRect, -1, -1); + NSRectFill(eraseRect); + + eraseRect = currentDrawingRect; + eraseRect.size.height = gTextBoxHeight; + NSRectFill(eraseRect); + + isErased = true; + } + + // Get the new drawing area + gCurrentPosition.x += gCurrentDelta.x; + gCurrentPosition.y += gCurrentDelta.y; + + imagePosition.x = (float) ((int)gCurrentPosition.x + gImageXIndent); + imagePosition.y = (float) (int)gCurrentPosition.y; + + // Calculate QuickDraw Rect for current text box + r.left = (float) ((int)gCurrentPosition.x); + r.right = r.left + gMovingRect.size.width; + r.top = viewBounds.size.height - imagePosition.y; + r.bottom = r.top + (int)MAXTEXTBOXHEIGHT; + r.top += TEXTBOXTOPBORDER; // Add a few pixels space below image + + TXNTextBoxOptionsData theOptions = {kTXNUseCGContextRefMask, kATSUStartAlignment, + kATSUNoJustification, 0, myContext }; + + cf_msg = CFStringCreateWithCString(NULL, msg, kCFStringEncodingMacRoman); + + [[NSColor whiteColor] set]; + + [ gBOINC_Logo compositeToPoint:imagePosition operation:NSCompositeCopy ]; + + err = TXNDrawCFStringTextBox ( cf_msg, &r, theStyle, &theOptions); + gTextBoxHeight = r.bottom - r.top + TEXTBOXTOPBORDER; + gMovingRect.size.height = [gBOINC_Logo size].height + gTextBoxHeight; + + CFRelease(cf_msg); + isErased = false; + + } else { // Empty or NULL message + if (!isErased) { + eraseRect = NSInsetRect(currentDrawingRect, -1, -1); + [[NSColor blackColor] set]; + isErased = true; + NSRectFill(eraseRect); + gTextBoxHeight = MAXTEXTBOXHEIGHT; + gMovingRect.size.height = [gBOINC_Logo size].height + gTextBoxHeight; + } + } - newFrequency = drawGraphics([ mainQDView qdPort ]); - [ mainQDView unlockFocus ]; - QDFlushPortBuffer([ mainQDView qdPort ], nil); if (newFrequency) [ self setAnimationTimeInterval:(1.0/newFrequency) ]; // setAnimationTimeInterval does not seem to be working, so we // throttle the screensaver directly here. - timeToUnblock = AddDurationToAbsolute(durationSecond/newFrequency, - frameStartTime); - MPDelayUntil(&timeToUnblock); - + timeToUnblock = AddDurationToAbsolute(durationSecond/newFrequency, frameStartTime); + MPDelayUntil(&timeToUnblock); } - (BOOL)hasConfigureSheet { @@ -211,5 +384,4 @@ NSString *gPathToBundleResources; [ NSApp endSheet:mConfigureSheet ]; } - @end diff --git a/clientscr/mac_saver_module.cpp b/clientscr/mac_saver_module.cpp index 6ee0247dcc..7e4120215f 100644 --- a/clientscr/mac_saver_module.cpp +++ b/clientscr/mac_saver_module.cpp @@ -41,13 +41,6 @@ #include "screensaver.h" //#include -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} // extern "C" -#endif // It would be nice to always display the scrolled progress info in case the // graphics application fails to show its window, but displaying the scrolled @@ -57,19 +50,9 @@ extern "C" { // Flags for testing & debugging #define CREATE_LOG 1 -#ifdef __cplusplus -extern "C" { -#endif -void print_to_log_file(const char *format, ...); -#ifdef __cplusplus -} - -void strip_cr(char *buf); -#endif - #define BANNER_GAP 30 /* Space between repeats of banner text */ #define BANNERDELTA 2 /* Number of pixels to move banner each frame */ -#define BANNERFREQUENCY 90 /* Number of times per second to scroll banner */ +#define BANNERFREQUENCY 30 /* Number of times per second to update text and logo */ #define NOBANNERFREQUENCY 4 /* Times per second to call drawGraphics if no banner */ #define STATUSUPDATEINTERVAL 5 /* seconds between status display updates */ #define TASK_RUN_CHECK_PERIOD 5 /* Seconds between safety check that task is actually running */ @@ -125,8 +108,8 @@ int initBOINCSaver(Boolean ispreview) { return gspScreensaver->Create(); } -int drawGraphics(GrafPtr aPort) { - return gspScreensaver->drawGraphics(aPort); +int drawGraphics(char **theMessage) { + return gspScreensaver->drawGraphics(theMessage); }; @@ -300,9 +283,10 @@ OSStatus CScreensaver::initBOINCApp() { // Returns new desired Animation Frequency (per second) or 0 for no change -int CScreensaver::drawGraphics(GrafPtr aPort) { - CGrafPtr savePort; - GDHandle saveGDH; +int CScreensaver::drawGraphics(char **theMessage) { + CGrafPtr aPort = NULL; +// CGrafPtr savePort; + // GDHandle saveGDH; int newFrequency = 15; pid_t myPid; OSStatus err; @@ -407,14 +391,17 @@ int CScreensaver::drawGraphics(GrafPtr aPort) { } // end switch (saverState) if (m_BannerText[0]) { +#if 0 GetGWorld(&savePort, &saveGDH); SetPort(aPort); drawBanner(aPort); SetGWorld(savePort, saveGDH); +#endif newFrequency = BANNERFREQUENCY; } else newFrequency = NOBANNERFREQUENCY; + *theMessage = m_BannerText; return newFrequency; } @@ -570,19 +557,20 @@ void CScreensaver::setBannerText(const char * msg, GrafPtr aPort) { if (msg == 0) m_BannerText[0] = 0; - if ((char *)m_CurrentBannerMessage != msg) + if (m_CurrentBannerMessage != msg) updateBannerText((char *)msg, aPort); } void CScreensaver::updateBannerText(char *msg, GrafPtr aPort) { - CGrafPtr savePort; - RGBColor saveBackColor; - Rect wRect; +// CGrafPtr savePort; +// RGBColor saveBackColor; +// Rect wRect; char *p, *s; - m_CurrentBannerMessage = (StringPtr)msg; + m_CurrentBannerMessage = msg; +#if 0 if (aPort == NULL) return; @@ -595,10 +583,13 @@ void CScreensaver::updateBannerText(char *msg, GrafPtr aPort) { BackColor ( blackColor ); EraseRect(&wRect); RGBBackColor(&saveBackColor); + #endif if (msg) { +#if 0 TextSize(24); TextFace(bold); +#endif s = msg; m_BannerText[0] = '\0'; do { @@ -612,12 +603,15 @@ void CScreensaver::updateBannerText(char *msg, GrafPtr aPort) { } } while (p); +#if 0 m_BannerWidth = TextWidth(m_BannerText, 0, strlen(m_BannerText)) + BANNER_GAP; // Round up m_BannerWidth to an integral multiple of BANNERDELTA m_BannerWidth = ((m_BannerWidth + BANNERDELTA - 1) / BANNERDELTA) * BANNERDELTA; +#endif } - SetPort(savePort); +// SetPort(savePort); + } @@ -791,7 +785,7 @@ OSErr CScreensaver::KillScreenSaver() { } -void CScreensaver::print_to_log_file(const char *format, ...) { +void print_to_log_file(const char *format, ...) { #if CREATE_LOG FILE *f; va_list args; @@ -823,7 +817,7 @@ void CScreensaver::print_to_log_file(const char *format, ...) { } #if CREATE_LOG -void CScreensaver::strip_cr(char *buf) +void strip_cr(char *buf) { char *theCR; diff --git a/clientscr/res/boinc_ss_logo.png b/clientscr/res/boinc_ss_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..75a070bf90305930ec9f8d4b0accedfe1268cb77 GIT binary patch literal 12340 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 LNkvXXu0mjf*=GF> literal 0 HcmV?d00001 diff --git a/mac_build/boinc.xcodeproj/project.pbxproj b/mac_build/boinc.xcodeproj/project.pbxproj index c114830a7f..1ff5d14a0d 100755 --- a/mac_build/boinc.xcodeproj/project.pbxproj +++ b/mac_build/boinc.xcodeproj/project.pbxproj @@ -230,6 +230,7 @@ DDA6BD2D0BD4551F008F7921 /* QTaskMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = DDA6BD100BD4551F008F7921 /* QTaskMemory.c */; }; DDAEC9FF07FA5A5C00A7BC36 /* SetVersion.C in Sources */ = {isa = PBXBuildFile; fileRef = DDAEC9E707FA58A000A7BC36 /* SetVersion.C */; }; DDB693500ABFE9C600689FD8 /* procinfo_mac.C in Sources */ = {isa = PBXBuildFile; fileRef = DDB6934F0ABFE9C600689FD8 /* procinfo_mac.C */; }; + DDB6E3EF0D5B27AA00ED12B8 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; DDB873990C85072500E0DE1F /* mac_saver_module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDB873960C85072500E0DE1F /* mac_saver_module.cpp */; }; DDB8739A0C85072500E0DE1F /* Mac_Saver_ModuleView.m in Sources */ = {isa = PBXBuildFile; fileRef = DDB873980C85072500E0DE1F /* Mac_Saver_ModuleView.m */; }; DDB873EE0C850BC800E0DE1F /* gutil.C in Sources */ = {isa = PBXBuildFile; fileRef = DD40825507D3076400163EF5 /* gutil.C */; }; @@ -242,6 +243,7 @@ DDB873F70C850BC800E0DE1F /* str_util.C in Sources */ = {isa = PBXBuildFile; fileRef = DD7BF7D70B8E7A9800A009F7 /* str_util.C */; }; DDB874470C850D3000E0DE1F /* graphics2_unix.C in Sources */ = {isa = PBXBuildFile; fileRef = DDB874450C850D3000E0DE1F /* graphics2_unix.C */; }; DDB874480C850D3000E0DE1F /* graphics2.C in Sources */ = {isa = PBXBuildFile; fileRef = DDB874460C850D3000E0DE1F /* graphics2.C */; }; + DDBC6CA50D5D458700564C49 /* boinc_ss_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = DDBC6CA40D5D458700564C49 /* boinc_ss_logo.png */; }; DDBD51760C169B770074905B /* LoginItemAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = DD1277BE081F3E73007B5DE1 /* LoginItemAPI.c */; }; DDBE74390C03B1C600453BB8 /* cs_platforms.C in Sources */ = {isa = PBXBuildFile; fileRef = DDBE74380C03B1C600453BB8 /* cs_platforms.C */; }; DDC3D55E0D507D1700BE6D23 /* BOINCClientManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC3D55C0D507D1700BE6D23 /* BOINCClientManager.cpp */; }; @@ -796,6 +798,7 @@ DDB874450C850D3000E0DE1F /* graphics2_unix.C */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = graphics2_unix.C; path = ../api/graphics2_unix.C; sourceTree = SOURCE_ROOT; }; DDB874460C850D3000E0DE1F /* graphics2.C */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = graphics2.C; path = ../api/graphics2.C; sourceTree = SOURCE_ROOT; }; DDB8D5A5081FC8C700A5A1E8 /* postinstall */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.csh; name = postinstall; path = ../mac_installer/postinstall; sourceTree = SOURCE_ROOT; }; + DDBC6CA40D5D458700564C49 /* boinc_ss_logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = boinc_ss_logo.png; path = ../clientscr/res/boinc_ss_logo.png; sourceTree = SOURCE_ROOT; }; DDBDF4A90987091800464F83 /* ValidateEmailAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ValidateEmailAddress.cpp; path = ../clientgui/ValidateEmailAddress.cpp; sourceTree = SOURCE_ROOT; }; DDBDF4AA0987091800464F83 /* ValidateEmailAddress.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ValidateEmailAddress.h; path = ../clientgui/ValidateEmailAddress.h; sourceTree = SOURCE_ROOT; }; DDBE74380C03B1C600453BB8 /* cs_platforms.C */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = cs_platforms.C; path = ../client/cs_platforms.C; sourceTree = SOURCE_ROOT; }; @@ -984,6 +987,7 @@ buildActionMask = 2147483647; files = ( DD130E740820C422001A0291 /* ScreenSaver.framework in Frameworks */, + DDB6E3EF0D5B27AA00ED12B8 /* Carbon.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1085,6 +1089,7 @@ isa = PBXGroup; children = ( DD0C5A8A0816711400CEC5D7 /* boinc.jpg */, + DDBC6CA40D5D458700564C49 /* boinc_ss_logo.png */, DDF3028907CCCE2C00701169 /* BOINCMgr.icns */, DD531BC50C193D3800742E50 /* MacInstaller.icns */, DD531BC70C193D5200742E50 /* MacUninstaller.icns */, @@ -1944,6 +1949,7 @@ DD616A3008150050006981C1 /* InfoPlist.strings in Resources */, DD0C5A8B0816711400CEC5D7 /* boinc.jpg in Resources */, DD48091F081A66F100A174AA /* BOINCSaver.nib in Resources */, + DDBC6CA50D5D458700564C49 /* boinc_ss_logo.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; };