2 * swarm.c - swarm of bees for xlock, the X Window System lockscreen.
4 * Copyright (c) 1991 by Patrick J. Naughton.
7 * 31-Aug-90: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org)
10 /* Ported to kscreensaver:
11 July 1997, Emanuel Pirker <epirker@edu.uni-klu.ac.at>
12 Contact me in case of problems, not the original author!
13 Last revised: 10-Jul-97
15 // layout management added 1998/04/19 by Mario Weilguni <mweilguni@kde.org>
25 #include <QVBoxLayout>
26 #include <QHBoxLayout>
29 #include <krandomsequence.h>
34 #define TIMES 4 /* number of time positions recorded */
35 #define BEEACC 2 /* acceleration of bees */
36 #define WASPACC 5 /* maximum acceleration of wasp */
37 #define BEEVEL 12 /* maximum bee velocity */
38 #define WASPVEL 10 /* maximum wasp velocity */
41 #define X(t,b) (sp->x[(t)*sp->beecount+(b)])
42 #define Y(t,b) (sp->y[(t)*sp->beecount+(b)])
43 #define balance_rand(v) (rnd.getLong(v)-((v)/2)) /* random number around 0 */
45 //ModeSpecOpt swarm_opts = {0, NULL, NULL, NULL};
51 int border
; /* wasp won't go closer than this to the edge */
52 int beecount
; /* number of bees */
53 XSegment segs
[MAXBATCH
]; /* bee lines */
54 XSegment old_segs
[MAXBATCH
]; /* old bee lines */
55 short x
[MAXBATCH
*TIMES
];
56 short y
[MAXBATCH
*TIMES
]; /* bee positions x[time][bee#] */
58 short yv
[MAXBATCH
]; /* bee velocities xv[bee#] */
65 static swarmstruct swarms
[MAXSCREENS
];
68 initswarm(Window win
, KRandomSequence
&rnd
)
70 swarmstruct
*sp
= &swarms
[screen
];
72 XWindowAttributes xwa
;
74 sp
->beecount
= batchcount
;
75 (void) XGetWindowAttributes(dsp
, win
, &xwa
);
76 sp
->width
= xwa
.width
;
77 sp
->height
= xwa
.height
;
79 sp
->border
= (sp
->width
+ sp
->height
) / 50;
81 /* Clear the background. */
82 XSetForeground(dsp
, Scr
[screen
].gc
, BlackPixel(dsp
, screen
));
83 XFillRectangle(dsp
, win
, Scr
[screen
].gc
, 0, 0, sp
->width
, sp
->height
);
85 /* Now static data structures. epirker */
87 //sp->segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
88 //sp->old_segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
89 //sp->x = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
90 //sp->y = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
91 //sp->xv = (short *) malloc(sizeof (short) * sp->beecount);
92 //sp->yv = (short *) malloc(sizeof (short) * sp->beecount);
94 /* Initialize point positions, velocities, etc. */
97 sp
->wx
[0] = sp
->border
+ rnd
.getLong(sp
->width
- 2 * sp
->border
);
98 sp
->wy
[0] = sp
->border
+ rnd
.getLong(sp
->height
- 2 * sp
->border
);
99 sp
->wx
[1] = sp
->wx
[0];
100 sp
->wy
[1] = sp
->wy
[0];
105 for (b
= 0; b
< sp
->beecount
; b
++) {
106 X(0, b
) = rnd
.getLong(sp
->width
);
108 Y(0, b
) = rnd
.getLong(sp
->height
);
110 sp
->xv
[b
] = balance_rand(7);
111 sp
->yv
[b
] = balance_rand(7);
118 drawswarm(Window win
, KRandomSequence
&rnd
)
120 swarmstruct
*sp
= &swarms
[screen
];
124 /* Age the arrays. */
125 sp
->wx
[2] = sp
->wx
[1];
126 sp
->wx
[1] = sp
->wx
[0];
127 sp
->wy
[2] = sp
->wy
[1];
128 sp
->wy
[1] = sp
->wy
[0];
130 sp
->wxv
+= balance_rand(WASPACC
);
131 sp
->wyv
+= balance_rand(WASPACC
);
133 /* Speed Limit Checks */
134 if (sp
->wxv
> WASPVEL
)
136 if (sp
->wxv
< -WASPVEL
)
138 if (sp
->wyv
> WASPVEL
)
140 if (sp
->wyv
< -WASPVEL
)
144 sp
->wx
[0] = sp
->wx
[1] + sp
->wxv
;
145 sp
->wy
[0] = sp
->wy
[1] + sp
->wyv
;
148 if ((sp
->wx
[0] < sp
->border
) || (sp
->wx
[0] > sp
->width
- sp
->border
- 1)) {
150 sp
->wx
[0] += sp
->wxv
;
152 if ((sp
->wy
[0] < sp
->border
) || (sp
->wy
[0] > sp
->height
- sp
->border
- 1)) {
154 sp
->wy
[0] += sp
->wyv
;
156 /* Don't let things settle down. */
157 sp
->xv
[rnd
.getLong(sp
->beecount
)] += balance_rand(3);
158 sp
->yv
[rnd
.getLong(sp
->beecount
)] += balance_rand(3);
161 for (b
= 0; b
< sp
->beecount
; b
++) {
162 int distance
, dx
, dy
;
164 /* Age the arrays. */
171 dx
= sp
->wx
[1] - X(1, b
);
172 dy
= sp
->wy
[1] - Y(1, b
);
173 distance
= abs(dx
) + abs(dy
); /* approximation */
176 sp
->xv
[b
] += (dx
* BEEACC
) / distance
;
177 sp
->yv
[b
] += (dy
* BEEACC
) / distance
;
179 /* Speed Limit Checks */
180 if (sp
->xv
[b
] > BEEVEL
)
182 if (sp
->xv
[b
] < -BEEVEL
)
184 if (sp
->yv
[b
] > BEEVEL
)
186 if (sp
->yv
[b
] < -BEEVEL
)
190 X(0, b
) = X(1, b
) + sp
->xv
[b
];
191 Y(0, b
) = Y(1, b
) + sp
->yv
[b
];
193 /* Fill the segment lists. */
194 sp
->segs
[b
].x1
= X(0, b
);
195 sp
->segs
[b
].y1
= Y(0, b
);
196 sp
->segs
[b
].x2
= X(1, b
);
197 sp
->segs
[b
].y2
= Y(1, b
);
198 sp
->old_segs
[b
].x1
= X(1, b
);
199 sp
->old_segs
[b
].y1
= Y(1, b
);
200 sp
->old_segs
[b
].x2
= X(2, b
);
201 sp
->old_segs
[b
].y2
= Y(2, b
);
204 XSetForeground(dsp
, Scr
[screen
].gc
, BlackPixel(dsp
, screen
));
205 XDrawLine(dsp
, win
, Scr
[screen
].gc
,
206 sp
->wx
[1], sp
->wy
[1], sp
->wx
[2], sp
->wy
[2]);
207 XDrawSegments(dsp
, win
, Scr
[screen
].gc
, sp
->old_segs
, sp
->beecount
);
209 XSetForeground(dsp
, Scr
[screen
].gc
, WhitePixel(dsp
, screen
));
210 XDrawLine(dsp
, win
, Scr
[screen
].gc
,
211 sp
->wx
[0], sp
->wy
[0], sp
->wx
[1], sp
->wy
[1]);
212 if (!mono
&& Scr
[screen
].npixels
> 2) {
213 XSetForeground(dsp
, Scr
[screen
].gc
, Scr
[screen
].pixels
[sp
->pix
]);
214 if (++sp
->pix
>= Scr
[screen
].npixels
)
217 XDrawSegments(dsp
, win
, Scr
[screen
].gc
, sp
->segs
, sp
->beecount
);
220 //-----------------------------------------------------------------------------
222 #include <qcheckbox.h>
228 #include <kmessagebox.h>
236 static kSwarmSaver
*saver
= NULL
;
238 void startScreenSaver( Drawable d
)
242 saver
= new kSwarmSaver( d
);
245 void stopScreenSaver()
252 int setupScreenSaver()
259 //-----------------------------------------------------------------------------
261 kSwarmSaver::kSwarmSaver( Drawable drawable
) : kScreenSaver( drawable
)
265 // Clear to background colour when exposed
266 XSetWindowBackground(QX11Info::display(), mDrawable
,
267 BlackPixel(QX11Info::display(), QX11Info::appScreen()));
269 batchcount
= maxLevels
;
272 initswarm( mDrawable
, rnd
);
274 timer
.start( speed
);
275 connect( &timer
, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
278 kSwarmSaver::~kSwarmSaver()
283 void kSwarmSaver::setSpeed( int spd
)
286 speed
= MAXSPEED
- spd
;
287 timer
.start( speed
);
290 void kSwarmSaver::setLevels( int l
)
292 batchcount
= maxLevels
= l
;
293 initswarm( mDrawable
, rnd
);
296 void kSwarmSaver::readSettings()
298 KConfig
*config
= klock_config();
299 config
->setGroup( "Settings" );
301 speed
= MAXSPEED
- config
->readNumEntry( "Speed", MAXSPEED
- DEFSPEED
);
302 maxLevels
= config
->readNumEntry( "MaxLevels", DEFBATCH
);
307 void kSwarmSaver::slotTimeout()
309 drawswarm( mDrawable
, rnd
);
312 //-----------------------------------------------------------------------------
314 kSwarmSetup::kSwarmSetup( QWidget
*parent
, const char *name
)
317 setCaption(i18n( "Setup Swarm Screen Saver" ));
318 setButtons(Ok
|Cancel
|Help
);
319 setDefaultButton(Ok
);
321 showButtonSeparator(true);
324 setButtonText( Help
, i18n( "A&bout" ) );
325 QWidget
*main
= new QWidget(this);
328 QHBoxLayout
*top
= new QHBoxLayout( main
/*, 0, spacingHint()*/ );
329 QVBoxLayout
*left
= new QVBoxLayout
;/*, spacingHint()*/
330 left
->addLayout(top
);
332 QLabel
*label
= new QLabel( i18n("Speed:"), main
);
334 left
->addWidget(label
);
336 QSlider
*slider
= new QSlider(Qt::Horizontal
,main
);
337 slider
->setMaximum(MAXSPEED
);
338 slider
->setMinimum(MINSPEED
);
339 slider
->setValue(speed
);
340 slider
->setMinimumSize( 120, 20 );
341 slider
->setTickPosition(QSlider::TicksBelow
);
342 slider
->setTickInterval(10);
343 connect( slider
, SIGNAL( valueChanged( int ) ),
344 SLOT( slotSpeed( int ) ) );
345 left
->addWidget(slider
);
347 label
= new QLabel( i18n("Number of bees:"), main
);
349 left
->addWidget(label
);
351 slider
= new QSlider(Qt::Horizontal
,main
);
352 slider
->setMaximum(MAXBATCH
);
353 slider
->setMinimum(MINBATCH
);
354 slider
->setValue(20);
356 slider
->setMinimumSize( 120, 20 );
357 slider
->setTickPosition(QSlider::TicksBelow
);
358 slider
->setTickInterval(20);
359 connect( slider
, SIGNAL( valueChanged( int ) ),
360 SLOT( slotLevels( int ) ) );
361 left
->addWidget(slider
);
364 preview
= new QWidget( main
);
365 preview
->setFixedSize( 220, 170 );
366 QPalette palette
= preview
->palette();
367 palette
.setColor(preview
->backgroundRole(), Qt::black
);
368 preview
->setPalette(palette
);
370 preview
->show(); // otherwise saver does not get correct size
371 saver
= new kSwarmSaver( preview
->winId() );
372 top
->addWidget(preview
);
377 void kSwarmSetup::readSettings()
379 KConfig
*config
= klock_config();
380 config
->setGroup( "Settings" );
382 speed
= config
->readNumEntry( "Speed", speed
);
384 if ( speed
> MAXSPEED
)
386 else if ( speed
< MINSPEED
)
389 maxLevels
= config
->readNumEntry( "MaxLevels", DEFBATCH
);
393 void kSwarmSetup::slotSpeed( int num
)
398 saver
->setSpeed( speed
);
401 void kSwarmSetup::slotLevels( int num
)
406 saver
->setLevels( maxLevels
);
409 void kSwarmSetup::slotOk()
411 KConfig
*config
= klock_config();
412 config
->setGroup( "Settings" );
415 sspeed
.setNum( speed
);
416 config
->writeEntry( "Speed", sspeed
);
419 slevels
.setNum( maxLevels
);
420 config
->writeEntry( "MaxLevels", slevels
);
427 void kSwarmSetup::slotHelp()
429 KMessageBox::information(this,
430 i18n("Swarm\n\nCopyright (c) 1991 by Patrick J. Naughton\n\nPorted to kscreensaver by Emanuel Pirker."),
431 i18n("About Swarm"));