PageRenderTime 38ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/kdeartwork-4.8.97/kscreensaver/xsavers/swarm.cpp

#
C++ | 435 lines | 311 code | 77 blank | 47 comment | 26 complexity | a1887737a2b29a0f2bade624a6663f1e MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, LGPL-3.0
  1. /*-
  2. * swarm.c - swarm of bees for xlock, the X Window System lockscreen.
  3. *
  4. * Copyright (c) 1991 by Patrick J. Naughton.
  5. *
  6. * Revision History:
  7. * 31-Aug-90: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org)
  8. */
  9. /* Ported to kscreensaver:
  10. July 1997, Emanuel Pirker <epirker@edu.uni-klu.ac.at>
  11. Contact me in case of problems, not the original author!
  12. Last revised: 10-Jul-97
  13. */
  14. // layout management added 1998/04/19 by Mario Weilguni <mweilguni@kde.org>
  15. #define MAXSPEED 100
  16. #define MINSPEED 0
  17. #define DEFSPEED 50
  18. #define MAXBATCH 200
  19. #define MINBATCH 0
  20. #define DEFBATCH 20
  21. #include <qslider.h>
  22. //Added by qt3to4:
  23. #include <QVBoxLayout>
  24. #include <QHBoxLayout>
  25. #include <kglobal.h>
  26. #include <kconfig.h>
  27. #include <krandomsequence.h>
  28. #include "xlock.h"
  29. #undef index
  30. #define TIMES 4 /* number of time positions recorded */
  31. #define BEEACC 2 /* acceleration of bees */
  32. #define WASPACC 5 /* maximum acceleration of wasp */
  33. #define BEEVEL 12 /* maximum bee velocity */
  34. #define WASPVEL 10 /* maximum wasp velocity */
  35. /* Macros */
  36. #define X(t,b) (sp->x[(t)*sp->beecount+(b)])
  37. #define Y(t,b) (sp->y[(t)*sp->beecount+(b)])
  38. #define balance_rand(v) (rnd.getLong(v)-((v)/2)) /* random number around 0 */
  39. //ModeSpecOpt swarm_opts = {0, NULL, NULL, NULL};
  40. typedef struct {
  41. int pix;
  42. int width;
  43. int height;
  44. int border; /* wasp won't go closer than this to the edge */
  45. int beecount; /* number of bees */
  46. XSegment segs[MAXBATCH]; /* bee lines */
  47. XSegment old_segs[MAXBATCH]; /* old bee lines */
  48. short x[MAXBATCH*TIMES];
  49. short y[MAXBATCH*TIMES]; /* bee positions x[time][bee#] */
  50. short xv[MAXBATCH];
  51. short yv[MAXBATCH]; /* bee velocities xv[bee#] */
  52. short wx[3];
  53. short wy[3];
  54. short wxv;
  55. short wyv;
  56. } swarmstruct;
  57. static swarmstruct swarms[MAXSCREENS];
  58. void
  59. initswarm(Window win, KRandomSequence &rnd)
  60. {
  61. swarmstruct *sp = &swarms[screen];
  62. int b;
  63. XWindowAttributes xwa;
  64. sp->beecount = batchcount;
  65. (void) XGetWindowAttributes(dsp, win, &xwa);
  66. sp->width = xwa.width;
  67. sp->height = xwa.height;
  68. sp->border = (sp->width + sp->height) / 50;
  69. /* Clear the background. */
  70. XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
  71. XFillRectangle(dsp, win, Scr[screen].gc, 0, 0, sp->width, sp->height);
  72. /* Now static data structures. epirker */
  73. //if (!sp->segs) {
  74. //sp->segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
  75. //sp->old_segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
  76. //sp->x = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
  77. //sp->y = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
  78. //sp->xv = (short *) malloc(sizeof (short) * sp->beecount);
  79. //sp->yv = (short *) malloc(sizeof (short) * sp->beecount);
  80. //}
  81. /* Initialize point positions, velocities, etc. */
  82. /* wasp */
  83. sp->wx[0] = sp->border + rnd.getLong(sp->width - 2 * sp->border);
  84. sp->wy[0] = sp->border + rnd.getLong(sp->height - 2 * sp->border);
  85. sp->wx[1] = sp->wx[0];
  86. sp->wy[1] = sp->wy[0];
  87. sp->wxv = 0;
  88. sp->wyv = 0;
  89. /* bees */
  90. for (b = 0; b < sp->beecount; b++) {
  91. X(0, b) = rnd.getLong(sp->width);
  92. X(1, b) = X(0, b);
  93. Y(0, b) = rnd.getLong(sp->height);
  94. Y(1, b) = Y(0, b);
  95. sp->xv[b] = balance_rand(7);
  96. sp->yv[b] = balance_rand(7);
  97. }
  98. }
  99. void
  100. drawswarm(Window win, KRandomSequence &rnd)
  101. {
  102. swarmstruct *sp = &swarms[screen];
  103. int b;
  104. /* <=- Wasp -=> */
  105. /* Age the arrays. */
  106. sp->wx[2] = sp->wx[1];
  107. sp->wx[1] = sp->wx[0];
  108. sp->wy[2] = sp->wy[1];
  109. sp->wy[1] = sp->wy[0];
  110. /* Accelerate */
  111. sp->wxv += balance_rand(WASPACC);
  112. sp->wyv += balance_rand(WASPACC);
  113. /* Speed Limit Checks */
  114. if (sp->wxv > WASPVEL)
  115. sp->wxv = WASPVEL;
  116. if (sp->wxv < -WASPVEL)
  117. sp->wxv = -WASPVEL;
  118. if (sp->wyv > WASPVEL)
  119. sp->wyv = WASPVEL;
  120. if (sp->wyv < -WASPVEL)
  121. sp->wyv = -WASPVEL;
  122. /* Move */
  123. sp->wx[0] = sp->wx[1] + sp->wxv;
  124. sp->wy[0] = sp->wy[1] + sp->wyv;
  125. /* Bounce Checks */
  126. if ((sp->wx[0] < sp->border) || (sp->wx[0] > sp->width - sp->border - 1)) {
  127. sp->wxv = -sp->wxv;
  128. sp->wx[0] += sp->wxv;
  129. }
  130. if ((sp->wy[0] < sp->border) || (sp->wy[0] > sp->height - sp->border - 1)) {
  131. sp->wyv = -sp->wyv;
  132. sp->wy[0] += sp->wyv;
  133. }
  134. /* Don't let things settle down. */
  135. sp->xv[rnd.getLong(sp->beecount)] += balance_rand(3);
  136. sp->yv[rnd.getLong(sp->beecount)] += balance_rand(3);
  137. /* <=- Bees -=> */
  138. for (b = 0; b < sp->beecount; b++) {
  139. int distance, dx, dy;
  140. /* Age the arrays. */
  141. X(2, b) = X(1, b);
  142. X(1, b) = X(0, b);
  143. Y(2, b) = Y(1, b);
  144. Y(1, b) = Y(0, b);
  145. /* Accelerate */
  146. dx = sp->wx[1] - X(1, b);
  147. dy = sp->wy[1] - Y(1, b);
  148. distance = abs(dx) + abs(dy); /* approximation */
  149. if (distance == 0)
  150. distance = 1;
  151. sp->xv[b] += (dx * BEEACC) / distance;
  152. sp->yv[b] += (dy * BEEACC) / distance;
  153. /* Speed Limit Checks */
  154. if (sp->xv[b] > BEEVEL)
  155. sp->xv[b] = BEEVEL;
  156. if (sp->xv[b] < -BEEVEL)
  157. sp->xv[b] = -BEEVEL;
  158. if (sp->yv[b] > BEEVEL)
  159. sp->yv[b] = BEEVEL;
  160. if (sp->yv[b] < -BEEVEL)
  161. sp->yv[b] = -BEEVEL;
  162. /* Move */
  163. X(0, b) = X(1, b) + sp->xv[b];
  164. Y(0, b) = Y(1, b) + sp->yv[b];
  165. /* Fill the segment lists. */
  166. sp->segs[b].x1 = X(0, b);
  167. sp->segs[b].y1 = Y(0, b);
  168. sp->segs[b].x2 = X(1, b);
  169. sp->segs[b].y2 = Y(1, b);
  170. sp->old_segs[b].x1 = X(1, b);
  171. sp->old_segs[b].y1 = Y(1, b);
  172. sp->old_segs[b].x2 = X(2, b);
  173. sp->old_segs[b].y2 = Y(2, b);
  174. }
  175. XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
  176. XDrawLine(dsp, win, Scr[screen].gc,
  177. sp->wx[1], sp->wy[1], sp->wx[2], sp->wy[2]);
  178. XDrawSegments(dsp, win, Scr[screen].gc, sp->old_segs, sp->beecount);
  179. XSetForeground(dsp, Scr[screen].gc, WhitePixel(dsp, screen));
  180. XDrawLine(dsp, win, Scr[screen].gc,
  181. sp->wx[0], sp->wy[0], sp->wx[1], sp->wy[1]);
  182. if (!mono && Scr[screen].npixels > 2) {
  183. XSetForeground(dsp, Scr[screen].gc, Scr[screen].pixels[sp->pix]);
  184. if (++sp->pix >= Scr[screen].npixels)
  185. sp->pix = 0;
  186. }
  187. XDrawSegments(dsp, win, Scr[screen].gc, sp->segs, sp->beecount);
  188. }
  189. //-----------------------------------------------------------------------------
  190. #include <qcheckbox.h>
  191. #include <qlabel.h>
  192. #include <qcolor.h>
  193. #include <qlayout.h>
  194. #include <QX11Info>
  195. #include <klocale.h>
  196. #include <kmessagebox.h>
  197. #include "swarm.h"
  198. #include "swarm.moc"
  199. #include "helpers.h"
  200. #undef Below
  201. static kSwarmSaver *saver = NULL;
  202. void startScreenSaver( Drawable d )
  203. {
  204. if ( saver )
  205. return;
  206. saver = new kSwarmSaver( d );
  207. }
  208. void stopScreenSaver()
  209. {
  210. if ( saver )
  211. delete saver;
  212. saver = NULL;
  213. }
  214. int setupScreenSaver()
  215. {
  216. kSwarmSetup dlg;
  217. return dlg.exec();
  218. }
  219. //-----------------------------------------------------------------------------
  220. kSwarmSaver::kSwarmSaver( Drawable drawable ) : kScreenSaver( drawable )
  221. {
  222. readSettings();
  223. // Clear to background colour when exposed
  224. XSetWindowBackground(QX11Info::display(), mDrawable,
  225. BlackPixel(QX11Info::display(), QX11Info::appScreen()));
  226. batchcount = maxLevels;
  227. initXLock( mGc );
  228. initswarm( mDrawable, rnd );
  229. timer.start( speed );
  230. connect( &timer, SIGNAL(timeout()), SLOT(slotTimeout()) );
  231. }
  232. kSwarmSaver::~kSwarmSaver()
  233. {
  234. timer.stop();
  235. }
  236. void kSwarmSaver::setSpeed( int spd )
  237. {
  238. timer.stop();
  239. speed = MAXSPEED - spd;
  240. timer.start( speed );
  241. }
  242. void kSwarmSaver::setLevels( int l )
  243. {
  244. batchcount = maxLevels = l;
  245. initswarm( mDrawable, rnd );
  246. }
  247. void kSwarmSaver::readSettings()
  248. {
  249. KConfig *config = klock_config();
  250. KConfigGroup group = config->group( "Settings" );
  251. speed = MAXSPEED - group.readEntry( "Speed", MAXSPEED - DEFSPEED );
  252. maxLevels = group.readEntry( "MaxLevels", DEFBATCH );
  253. delete config;
  254. }
  255. void kSwarmSaver::slotTimeout()
  256. {
  257. drawswarm( mDrawable, rnd );
  258. }
  259. //-----------------------------------------------------------------------------
  260. kSwarmSetup::kSwarmSetup( QWidget *parent, const char *name )
  261. : KDialog( parent)
  262. {
  263. setCaption(i18n( "Setup Swarm Screen Saver" ));
  264. setButtons(Ok|Cancel|Help);
  265. setDefaultButton(Ok);
  266. setModal(true);
  267. showButtonSeparator(true);
  268. readSettings();
  269. setButtonText( Help, i18n( "A&bout" ) );
  270. QWidget *main = new QWidget(this);
  271. setMainWidget(main);
  272. QHBoxLayout *top = new QHBoxLayout(main );
  273. QVBoxLayout *left = new QVBoxLayout;
  274. top->addLayout(left);
  275. QLabel *label = new QLabel( i18n("Speed:"), main );
  276. min_size(label);
  277. left->addWidget(label);
  278. QSlider *slider = new QSlider(Qt::Horizontal,main);
  279. slider->setMaximum(MAXSPEED);
  280. slider->setMinimum(MINSPEED);
  281. slider->setValue(speed);
  282. slider->setMinimumSize( 120, 20 );
  283. slider->setTickPosition(QSlider::TicksBelow);
  284. slider->setTickInterval(10);
  285. connect( slider, SIGNAL(valueChanged(int)),
  286. SLOT(slotSpeed(int)) );
  287. left->addWidget(slider);
  288. label = new QLabel( i18n("Number of bees:"), main );
  289. min_size(label);
  290. left->addWidget(label);
  291. slider = new QSlider(Qt::Horizontal,main);
  292. slider->setMaximum(MAXBATCH);
  293. slider->setMinimum(MINBATCH);
  294. slider->setValue(20);
  295. slider->setMinimumSize( 120, 20 );
  296. slider->setTickPosition(QSlider::TicksBelow);
  297. slider->setTickInterval(20);
  298. connect( slider, SIGNAL(valueChanged(int)),
  299. SLOT(slotLevels(int)) );
  300. left->addWidget(slider);
  301. left->addStretch();
  302. preview = new QWidget( main );
  303. preview->setFixedSize( 220, 170 );
  304. QPalette palette = preview->palette();
  305. palette.setColor(preview->backgroundRole(), Qt::black);
  306. preview->setPalette(palette);
  307. preview->setAutoFillBackground(true);
  308. preview->show(); // otherwise saver does not get correct size
  309. saver = new kSwarmSaver( preview->winId() );
  310. top->addWidget(preview);
  311. top->addStretch();
  312. connect(this,SIGNAL(okClicked()),this,SLOT(slotOk()));
  313. connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
  314. }
  315. void kSwarmSetup::readSettings()
  316. {
  317. KConfig *config = klock_config();
  318. KConfigGroup group = config->group( "Settings" );
  319. speed = group.readEntry( "Speed", speed );
  320. if ( speed > MAXSPEED )
  321. speed = MAXSPEED;
  322. else if ( speed < MINSPEED )
  323. speed = MINSPEED;
  324. maxLevels = group.readEntry( "MaxLevels", DEFBATCH );
  325. delete config;
  326. }
  327. void kSwarmSetup::slotSpeed( int num )
  328. {
  329. speed = num;
  330. if ( saver )
  331. saver->setSpeed( speed );
  332. }
  333. void kSwarmSetup::slotLevels( int num )
  334. {
  335. maxLevels = num;
  336. if ( saver )
  337. saver->setLevels( maxLevels );
  338. }
  339. void kSwarmSetup::slotOk()
  340. {
  341. KConfig *config = klock_config();
  342. KConfigGroup group = config->group( "Settings" );
  343. QString sspeed;
  344. sspeed.setNum( speed );
  345. group.writeEntry( "Speed", sspeed );
  346. QString slevels;
  347. slevels.setNum( maxLevels );
  348. group.writeEntry( "MaxLevels", slevels );
  349. config->sync();
  350. delete config;
  351. accept();
  352. }
  353. void kSwarmSetup::slotHelp()
  354. {
  355. KMessageBox::information(this,
  356. i18n("Swarm\n\nCopyright (c) 1991 by Patrick J. Naughton\n\nPorted to kscreensaver by Emanuel Pirker."),
  357. i18n("About Swarm"));
  358. }