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.