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 colorContext
= QColor::enterAllocContext();
272 batchcount
= maxLevels
;
275 initswarm( mDrawable
, rnd
);
277 timer
.start( speed
);
278 connect( &timer
, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
281 kSwarmSaver::~kSwarmSaver()
284 QColor::leaveAllocContext();
285 QColor::destroyAllocContext( colorContext
);
288 void kSwarmSaver::setSpeed( int spd
)
291 speed
= MAXSPEED
- spd
;
292 timer
.start( speed
);
295 void kSwarmSaver::setLevels( int l
)
297 batchcount
= maxLevels
= l
;
298 initswarm( mDrawable
, rnd
);
301 void kSwarmSaver::readSettings()
303 KConfig
*config
= klock_config();
304 config
->setGroup( "Settings" );
306 speed
= MAXSPEED
- config
->readNumEntry( "Speed", MAXSPEED
- DEFSPEED
);
307 maxLevels
= config
->readNumEntry( "MaxLevels", DEFBATCH
);
312 void kSwarmSaver::slotTimeout()
314 drawswarm( mDrawable
, rnd
);
317 //-----------------------------------------------------------------------------
319 kSwarmSetup::kSwarmSetup( QWidget
*parent
, const char *name
)
320 : KDialogBase( parent
, name
, true, i18n( "Setup Swarm Screen Saver" ),
321 Ok
|Cancel
|Help
, Ok
, true )
325 setButtonText( Help
, i18n( "A&bout" ) );
326 QWidget
*main
= makeMainWidget();
328 QHBoxLayout
*top
= new QHBoxLayout( main
/*, 0, spacingHint()*/ );
329 QVBoxLayout
*left
= new QVBoxLayout(top
/*, spacingHint()*/);
331 QLabel
*label
= new QLabel( i18n("Speed:"), main
);
333 left
->addWidget(label
);
335 QSlider
*slider
= new QSlider(MINSPEED
, MAXSPEED
, 10, speed
,
336 Qt::Horizontal
, main
);
337 slider
->setMinimumSize( 120, 20 );
338 slider
->setTickPosition(QSlider::TicksBelow
);
339 slider
->setTickInterval(10);
340 connect( slider
, SIGNAL( valueChanged( int ) ),
341 SLOT( slotSpeed( int ) ) );
342 left
->addWidget(slider
);
344 label
= new QLabel( i18n("Number of bees:"), main
);
346 left
->addWidget(label
);
348 slider
= new QSlider(MINBATCH
, MAXBATCH
, 20, maxLevels
, Qt::Horizontal
, main
);
349 slider
->setMinimumSize( 120, 20 );
350 slider
->setTickPosition(QSlider::TicksBelow
);
351 slider
->setTickInterval(20);
352 connect( slider
, SIGNAL( valueChanged( int ) ),
353 SLOT( slotLevels( int ) ) );
354 left
->addWidget(slider
);
357 preview
= new QWidget( main
);
358 preview
->setFixedSize( 220, 170 );
359 preview
->setBackgroundColor( Qt::black
);
360 preview
->show(); // otherwise saver does not get correct size
361 saver
= new kSwarmSaver( preview
->winId() );
362 top
->addWidget(preview
);
367 void kSwarmSetup::readSettings()
369 KConfig
*config
= klock_config();
370 config
->setGroup( "Settings" );
372 speed
= config
->readNumEntry( "Speed", speed
);
374 if ( speed
> MAXSPEED
)
376 else if ( speed
< MINSPEED
)
379 maxLevels
= config
->readNumEntry( "MaxLevels", DEFBATCH
);
383 void kSwarmSetup::slotSpeed( int num
)
388 saver
->setSpeed( speed
);
391 void kSwarmSetup::slotLevels( int num
)
396 saver
->setLevels( maxLevels
);
399 void kSwarmSetup::slotOk()
401 KConfig
*config
= klock_config();
402 config
->setGroup( "Settings" );
405 sspeed
.setNum( speed
);
406 config
->writeEntry( "Speed", sspeed
);
409 slevels
.setNum( maxLevels
);
410 config
->writeEntry( "MaxLevels", slevels
);
417 void kSwarmSetup::slotHelp()
419 KMessageBox::information(this,
420 i18n("Swarm\n\nCopyright (c) 1991 by Patrick J. Naughton\n\nPorted to kscreensaver by Emanuel Pirker."),
421 i18n("About Swarm"));