This is ScreenSaver.m in view mode; [Download] [Up]
// The source for the loginwindow screensaver is due to Eric P. Scott. // A very small number of modifications were made by myself to add // blacking behavior and also the TimeToMove and TimeToBlack defaults. // Works like a charm under NS 3.1, but since it uses an unreleased API, // there is no guarantee of anything in future versions. - David Bau #import <libc.h> #import <appkit/appkit.h> @interface ImageView:View { id image; id hostname; NXRect textFrame; NXRect imageFrame; List *screenWindows; double timeToMove; double timeToBlack; long startTime; int blackened; } + initialize; - drawSelf:(const NXRect *)rects:(int)rectCount; - moveImage; - moveText; - oneStep; - initFrame:(const NXRect *)frameRect; - init; - stopScreenSaver; - startScreenSaver; - (double)interval; @end @interface ScreenSaver:Object { id view; id saver; ImageView *imageSaver; id selector; float timeout; id pie; id timeout_field; DPSTimedEntry te; } + alloc; - startScreenSaver; - stopScreenSaver; - createScreenSaver; - step; @end float frandom(void) { return (random()&0x7fffffff)/(float)2147483648.0; } float randBetween(float low, float high) { if (low>high) { register float temp; temp=low; low=high; high=temp; } high-=low; high*=frandom(); return low+high; } @implementation ImageView + initialize { static NXDefaultsVector ScreenSaverDefaults = { {"TimeToMove", "120"}, {"TimeToBlack", "1800"}, {NULL} }; NXRegisterDefaults("loginwindow",ScreenSaverDefaults); return self; } - drawSelf:(const NXRect *)rects:(int)rectCount { PSsetgray(NX_BLACK); NXRectFill(rects); if (!blackened) { [image composite:NX_SOVER toPoint:&imageFrame.origin]; [hostname drawInside:&textFrame inView:self]; } return self; } - moveImage { imageFrame.origin.x=(float)floor((double)randBetween(0.0, bounds.size.width-imageFrame.size.width)); imageFrame.origin.y=(float)floor((double)randBetween(0.0, bounds.size.height-imageFrame.size.height)); return self; } - moveText { register int i, j, k, l; i=0; do { textFrame.origin.x=floor((double)randBetween(0.0, bounds.size.width-textFrame.size.width)); textFrame.origin.y=floor((double)randBetween(0.0, bounds.size.height-textFrame.size.height)); if (!NXIntersectsRect(&textFrame, &imageFrame)) break; } while (++i<50); if (i>49) { register double w; if (imageFrame.size.width/2+imageFrame.origin.x< bounds.size.width/2) { k=imageFrame.origin.x+imageFrame.size.width; w=bounds.size.width; } else { k=0; w=imageFrame.origin.x; } l=w; if (imageFrame.size.height/2+imageFrame.origin.y< bounds.size.height/2) { i=imageFrame.origin.y+imageFrame.size.height; w=bounds.size.height; } else { i=0; w=imageFrame.origin.y; } j=w; if (textFrame.size.width<l-k&&textFrame.size.height<j-i) { textFrame.origin.x=k; textFrame.origin.y=i; } } return self; } - oneStep { struct timeval tv; struct timezone tz; if (blackened) return self; /* check if TimeToBlack has elapsed */ if (timeToBlack>0.0) { gettimeofday(&tv,&tz); if (tv.tv_sec-startTime>=timeToBlack) blackened=YES; } [self moveImage]; [self moveText]; [self display]; return self; } - initFrame:(const NXRect *)frameRect { extern char *lwHostName(char *); register char *h; id b; char hn[256]; char hn2[512]; char path[1026]; [super initFrame:frameRect]; /* pick up image */ (void)sprintf(path, "%s/%s", [[NXBundle mainBundle] directory], "ScreenSaver.bundle"); b=[[NXBundle alloc] initForDirectory:path]; [b getPath:path forResource:"image.tiff" ofType:(const char *)NULL]; image=[[NXImage alloc] initFromFile:path]; [image getSize:&imageFrame.size]; /* pick up host name */ if (h=lwHostName(hn)) { register int i; for (i=0;i<strlen(h);i++) { hn2[i*2]=h[i]; hn2[i*2+1]=' '; } hn2[strlen(h)*2]='\0'; hostname=[[TextFieldCell alloc] initTextCell:hn2]; [hostname setEditable:NO]; [hostname setTextGray:0.333]; [hostname setBackgroundGray:NX_BLACK]; [hostname setFont:[Font newFont:"Times-Italic" size:36.0]]; [hostname calcCellSize:&textFrame.size]; } [self oneStep]; return self; } - init { extern void makeWindowBlack(int); register id w; NXRect fr; const NXScreen *scrns; int nscrns; if (!screenWindows) { register int i; [NXApp getScreens:&scrns count:&nscrns]; screenWindows=[[List alloc] initCount:nscrns]; for (i=0;i<nscrns;i++) { w=[[Window alloc] initContent:&scrns[i].screenBounds style:NX_PLAINSTYLE backing:NX_NONRETAINED buttonMask:0 defer:NO]; [screenWindows addObject:w]; [w setBackgroundGray:NX_BLACK]; [w addToEventMask:NX_MOUSEMOVEDMASK]; PSsetwindowlevel(50, [w windowNum]); makeWindowBlack([w windowNum]); } w=[screenWindows objectAt:0]; [w getFrame:&fr]; w=[w contentView]; [w getBounds:&fr]; [self initFrame:&fr]; srandom(time((long *)NULL)); [w addSubview:self]; } return self; } - stopScreenSaver { [screenWindows makeObjectsPerform:@selector(orderOut:) with:self]; return self; } - startScreenSaver { struct timeval tv; struct timezone tz; /* pick up starting time */ gettimeofday(&tv,&tz); startTime=tv.tv_sec; /* don't blacken at the start */ blackened=NO; /* pick up defaults */ sscanf(NXReadDefault("loginwindow","TimeToMove"),"%lf",&timeToMove); if (timeToMove>1800.0) timeToMove=1800.0; if (timeToMove<1.0) timeToMove=1.0; sscanf(NXReadDefault("loginwindow","TimeToBlack"),"%lf",&timeToBlack); if (timeToBlack<0.0) timeToBlack= -1.0; /* make the screensaver visible */ [screenWindows makeObjectsPerform:@selector(orderFront:) with:self]; [screenWindows makeObjectsPerform:@selector(display)]; return self; } - (double)interval { return timeToMove; } @end void step(DPSTimedEntry te, double now, void *userData) { [(ScreenSaver *)userData step]; } @implementation ScreenSaver + alloc { static ScreenSaver *inst; if (inst) return inst; self=[super alloc]; inst=self; imageSaver=[[ImageView alloc] init]; return self; } - startScreenSaver { PShidecursor(); [self createScreenSaver]; if ([saver respondsTo:@selector(startScreenSaver)]) [saver startScreenSaver]; te=DPSAddTimedEntry([saver interval], step, (void *)self, NX_MODALRESPTHRESHOLD); return self; } - stopScreenSaver { PSshowcursor(); DPSRemoveTimedEntry(te); if ([saver respondsTo:@selector(stopScreenSaver)]) [saver stopScreenSaver]; return self; } - createScreenSaver { saver=(id)imageSaver; return self; } - step { [saver lockFocus]; [saver oneStep]; [saver unlockFocus]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.