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>
26 #include <QVBoxLayout>
27 #include <QHBoxLayout>
30 #include <krandomsequence.h>
35 #define TIMES 4 /* number of time positions recorded */
36 #define BEEACC 2 /* acceleration of bees */
37 #define WASPACC 5 /* maximum acceleration of wasp */
38 #define BEEVEL 12 /* maximum bee velocity */
39 #define WASPVEL 10 /* maximum wasp velocity */
42 #define X(t,b) (sp->x[(t)*sp->beecount+(b)])
43 #define Y(t,b) (sp->y[(t)*sp->beecount+(b)])
44 #define balance_rand(v) (rnd.getLong(v)-((v)/2)) /* random number around 0 */
46 //ModeSpecOpt swarm_opts = {0, NULL, NULL, NULL};
52 int border
; /* wasp won't go closer than this to the edge */
53 int beecount
; /* number of bees */
54 XSegment segs
[MAXBATCH
]; /* bee lines */
55 XSegment old_segs
[MAXBATCH
]; /* old bee lines */
56 short x
[MAXBATCH
*TIMES
];
57 short y
[MAXBATCH
*TIMES
]; /* bee positions x[time][bee#] */
59 short yv
[MAXBATCH
]; /* bee velocities xv[bee#] */
66 static swarmstruct swarms
[MAXSCREENS
];
69 initswarm(Window win
, KRandomSequence
&rnd
)
71 swarmstruct
*sp
= &swarms
[screen
];
73 XWindowAttributes xwa
;
75 sp
->beecount
= batchcount
;
76 (void) XGetWindowAttributes(dsp
, win
, &xwa
);
77 sp
->width
= xwa
.width
;
78 sp
->height
= xwa
.height
;
80 sp
->border
= (sp
->width
+ sp
->height
) / 50;
82 /* Clear the background. */
83 XSetForeground(dsp
, Scr
[screen
].gc
, BlackPixel(dsp
, screen
));
84 XFillRectangle(dsp
, win
, Scr
[screen
].gc
, 0, 0, sp
->width
, sp
->height
);
86 /* Now static data structures. epirker */
88 //sp->segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
89 //sp->old_segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
90 //sp->x = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
91 //sp->y = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
92 //sp->xv = (short *) malloc(sizeof (short) * sp->beecount);
93 //sp->yv = (short *) malloc(sizeof (short) * sp->beecount);
95 /* Initialize point positions, velocities, etc. */
98 sp
->wx
[0] = sp
->border
+ rnd
.getLong(sp
->width
- 2 * sp
->border
);
99 sp
->wy
[0] = sp
->border
+ rnd
.getLong(sp
->height
- 2 * sp
->border
);
100 sp
->wx
[1] = sp
->wx
[0];
101 sp
->wy
[1] = sp
->wy
[0];
106 for (b
= 0; b
< sp
->beecount
; b
++) {
107 X(0, b
) = rnd
.getLong(sp
->width
);
109 Y(0, b
) = rnd
.getLong(sp
->height
);
111 sp
->xv
[b
] = balance_rand(7);
112 sp
->yv
[b
] = balance_rand(7);
119 drawswarm(Window win
, KRandomSequence
&rnd
)
121 swarmstruct
*sp
= &swarms
[screen
];
125 /* Age the arrays. */
126 sp
->wx
[2] = sp
->wx
[1];
127 sp
->wx
[1] = sp
->wx
[0];
128 sp
->wy
[2] = sp
->wy
[1];
129 sp
->wy
[1] = sp
->wy
[0];
131 sp
->wxv
+= balance_rand(WASPACC
);
132 sp
->wyv
+= balance_rand(WASPACC
);
134 /* Speed Limit Checks */
135 if (sp
->wxv
> WASPVEL
)
137 if (sp
->wxv
< -WASPVEL
)
139 if (sp
->wyv
> WASPVEL
)
141 if (sp
->wyv
< -WASPVEL
)
145 sp
->wx
[0] = sp
->wx
[1] + sp
->wxv
;
146 sp
->wy
[0] = sp
->wy
[1] + sp
->wyv
;
149 if ((sp
->wx
[0] < sp
->border
) || (sp
->wx
[0] > sp
->width
- sp
->border
- 1)) {
151 sp
->wx
[0] += sp
->wxv
;
153 if ((sp
->wy
[0] < sp
->border
) || (sp
->wy
[0] > sp
->height
- sp
->border
- 1)) {
155 sp
->wy
[0] += sp
->wyv
;
157 /* Don't let things settle down. */
158 sp
->xv
[rnd
.getLong(sp
->beecount
)] += balance_rand(3);
159 sp
->yv
[rnd
.getLong(sp
->beecount
)] += balance_rand(3);
162 for (b
= 0; b
< sp
->beecount
; b
++) {
163 int distance
, dx
, dy
;
165 /* Age the arrays. */
172 dx
= sp
->wx
[1] - X(1, b
);
173 dy
= sp
->wy
[1] - Y(1, b
);
174 distance
= abs(dx
) + abs(dy
); /* approximation */
177 sp
->xv
[b
] += (dx
* BEEACC
) / distance
;
178 sp
->yv
[b
] += (dy
* BEEACC
) / distance
;
180 /* Speed Limit Checks */
181 if (sp
->xv
[b
] > BEEVEL
)
183 if (sp
->xv
[b
] < -BEEVEL
)
185 if (sp
->yv
[b
] > BEEVEL
)
187 if (sp
->yv
[b
] < -BEEVEL
)
191 X(0, b
) = X(1, b
) + sp
->xv
[b
];
192 Y(0, b
) = Y(1, b
) + sp
->yv
[b
];
194 /* Fill the segment lists. */
195 sp
->segs
[b
].x1
= X(0, b
);
196 sp
->segs
[b
].y1
= Y(0, b
);
197 sp
->segs
[b
].x2
= X(1, b
);
198 sp
->segs
[b
].y2
= Y(1, b
);
199 sp
->old_segs
[b
].x1
= X(1, b
);
200 sp
->old_segs
[b
].y1
= Y(1, b
);
201 sp
->old_segs
[b
].x2
= X(2, b
);
202 sp
->old_segs
[b
].y2
= Y(2, b
);
205 XSetForeground(dsp
, Scr
[screen
].gc
, BlackPixel(dsp
, screen
));
206 XDrawLine(dsp
, win
, Scr
[screen
].gc
,
207 sp
->wx
[1], sp
->wy
[1], sp
->wx
[2], sp
->wy
[2]);
208 XDrawSegments(dsp
, win
, Scr
[screen
].gc
, sp
->old_segs
, sp
->beecount
);
210 XSetForeground(dsp
, Scr
[screen
].gc
, WhitePixel(dsp
, screen
));
211 XDrawLine(dsp
, win
, Scr
[screen
].gc
,
212 sp
->wx
[0], sp
->wy
[0], sp
->wx
[1], sp
->wy
[1]);
213 if (!mono
&& Scr
[screen
].npixels
> 2) {
214 XSetForeground(dsp
, Scr
[screen
].gc
, Scr
[screen
].pixels
[sp
->pix
]);
215 if (++sp
->pix
>= Scr
[screen
].npixels
)
218 XDrawSegments(dsp
, win
, Scr
[screen
].gc
, sp
->segs
, sp
->beecount
);
221 //-----------------------------------------------------------------------------
223 #include <qcheckbox.h>
229 #include <kmessagebox.h>
237 static kSwarmSaver
*saver
= NULL
;
239 void startScreenSaver( Drawable d
)
243 saver
= new kSwarmSaver( d
);
246 void stopScreenSaver()
253 int setupScreenSaver()
260 //-----------------------------------------------------------------------------
262 kSwarmSaver::kSwarmSaver( Drawable drawable
) : kScreenSaver( drawable
)
266 // Clear to background colour when exposed
267 XSetWindowBackground(QX11Info::display(), mDrawable
,
268 BlackPixel(QX11Info::display(), QX11Info::appScreen()));
270 batchcount
= maxLevels
;
273 initswarm( mDrawable
, rnd
);
275 timer
.start( speed
);
276 connect( &timer
, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
279 kSwarmSaver::~kSwarmSaver()
284 void kSwarmSaver::setSpeed( int spd
)
287 speed
= MAXSPEED
- spd
;
288 timer
.start( speed
);
291 void kSwarmSaver::setLevels( int l
)
293 batchcount
= maxLevels
= l
;
294 initswarm( mDrawable
, rnd
);
297 void kSwarmSaver::readSettings()
299 KConfig
*config
= klock_config();
300 config
->setGroup( "Settings" );
302 speed
= MAXSPEED
- config
->readNumEntry( "Speed", MAXSPEED
- DEFSPEED
);
303 maxLevels
= config
->readNumEntry( "MaxLevels", DEFBATCH
);
308 void kSwarmSaver::slotTimeout()
310 drawswarm( mDrawable
, rnd
);
313 //-----------------------------------------------------------------------------
315 kSwarmSetup::kSwarmSetup( QWidget
*parent
, const char *name
)
316 : KDialogBase( parent
, name
, true, i18n( "Setup Swarm Screen Saver" ),
317 Ok
|Cancel
|Help
, Ok
, true )
321 setButtonText( Help
, i18n( "A&bout" ) );
322 QWidget
*main
= makeMainWidget();
324 QHBoxLayout
*top
= new QHBoxLayout( main
/*, 0, spacingHint()*/ );
325 QVBoxLayout
*left
= new QVBoxLayout(0L);/*, spacingHint()*/
326 left
->addLayout(top
);
328 QLabel
*label
= new QLabel( i18n("Speed:"), main
);
330 left
->addWidget(label
);
332 QSlider
*slider
= new QSlider(Qt::Horizontal
,main
);
333 slider
->setMaximum(MAXSPEED
);
334 slider
->setMinimum(MINSPEED
);
335 slider
->setValue(speed
);
336 slider
->setMinimumSize( 120, 20 );
337 slider
->setTickPosition(QSlider::TicksBelow
);
338 slider
->setTickInterval(10);
339 connect( slider
, SIGNAL( valueChanged( int ) ),
340 SLOT( slotSpeed( int ) ) );
341 left
->addWidget(slider
);
343 label
= new QLabel( i18n("Number of bees:"), main
);
345 left
->addWidget(label
);
347 slider
= new QSlider(Qt::Horizontal
,main
);
348 slider
->setMaximum(MAXBATCH
);
349 slider
->setMinimum(MINBATCH
);
350 slider
->setValue(20);
352 slider
->setMinimumSize( 120, 20 );
353 slider
->setTickPosition(QSlider::TicksBelow
);
354 slider
->setTickInterval(20);
355 connect( slider
, SIGNAL( valueChanged( int ) ),
356 SLOT( slotLevels( int ) ) );
357 left
->addWidget(slider
);
360 preview
= new QWidget( main
);
361 preview
->setFixedSize( 220, 170 );
362 QPalette palette
= preview
->palette();
363 palette
.setColor(preview
->backgroundRole(), Qt::black
);
364 preview
->setPalette(palette
);
366 preview
->show(); // otherwise saver does not get correct size
367 saver
= new kSwarmSaver( preview
->winId() );
368 top
->addWidget(preview
);
373 void kSwarmSetup::readSettings()
375 KConfig
*config
= klock_config();
376 config
->setGroup( "Settings" );
378 speed
= config
->readNumEntry( "Speed", speed
);
380 if ( speed
> MAXSPEED
)
382 else if ( speed
< MINSPEED
)
385 maxLevels
= config
->readNumEntry( "MaxLevels", DEFBATCH
);
389 void kSwarmSetup::slotSpeed( int num
)
394 saver
->setSpeed( speed
);
397 void kSwarmSetup::slotLevels( int num
)
402 saver
->setLevels( maxLevels
);
405 void kSwarmSetup::slotOk()
407 KConfig
*config
= klock_config();
408 config
->setGroup( "Settings" );
411 sspeed
.setNum( speed
);
412 config
->writeEntry( "Speed", sspeed
);
415 slevels
.setNum( maxLevels
);
416 config
->writeEntry( "MaxLevels", slevels
);
423 void kSwarmSetup::slotHelp()
425 KMessageBox::information(this,
426 i18n("Swarm\n\nCopyright (c) 1991 by Patrick J. Naughton\n\nPorted to kscreensaver by Emanuel Pirker."),
427 i18n("About Swarm"));