2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies of the Software, its documentation and marketing & publicity
13 * materials, and acknowledgment shall be given in the documentation, materials
14 * and software packages that this Software was used.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #define E_FX_RAINDROPS 0
35 #define E_FX_IMAGESPINNER 0
37 /* FIXME - Needs cleaning up */
40 #define M_PI_2 (3.141592654 / 2)
45 #define FX_OP_TOGGLE 3
49 void (*init_func) (const char *name);
50 void (*desk_func) (void);
51 void (*quit_func) (void);
52 void (*pause_func) (void);
58 /* As of composite 0.4 we need to set the clip region */
59 #define SET_GC_CLIP(eo, gc) ECompMgrWinClipToGC(eo, gc)
61 #define SET_GC_CLIP(eo, gc)
64 /****************************** RIPPLES *************************************/
66 #define fx_ripple_waterh 64
67 static Pixmap fx_ripple_above = None;
68 static Win fx_ripple_win = NULL;
69 static int fx_ripple_count = 0;
70 static Timer *fx_ripple_timer = NULL;
73 FX_ripple_timeout(void *data __UNUSED__)
75 static double incv = 0, inch = 0;
76 static GC gc1 = 0, gc = 0;
80 bgeo = DeskGetBackgroundObj(DesksGetCurrent());
82 if (fx_ripple_above == None)
86 fx_ripple_win = EobjGetWin(bgeo);
89 ECreatePixmap(fx_ripple_win, WinGetW(VROOT),
90 fx_ripple_waterh * 2, 0);
95 gcv.subwindow_mode = IncludeInferiors;
96 gc = EXCreateGC(WinGetXwin(fx_ripple_win), GCSubwindowMode, &gcv);
97 gc1 = EXCreateGC(WinGetXwin(fx_ripple_win), 0L, &gcv);
100 if (fx_ripple_count == 0)
101 XCopyArea(disp, WinGetXwin(fx_ripple_win), fx_ripple_above, gc, 0,
102 WinGetH(VROOT) - (fx_ripple_waterh * 3), WinGetW(VROOT),
103 fx_ripple_waterh * 2, 0, 0);
106 if (fx_ripple_count > 32)
110 if (incv > (M_PI_2 * 4))
113 if (inch > (M_PI_2 * 4))
116 SET_GC_CLIP(bgeo, gc1);
118 for (y = 0; y < fx_ripple_waterh; y++)
123 p = (((double)(fx_ripple_waterh - y)) / ((double)fx_ripple_waterh));
124 a = p * p * 48 + incv;
125 yoff = y + (int)(sin(a) * 7) + 1;
126 yy = (fx_ripple_waterh * 2) - yoff;
127 aa = p * p * 64 + inch;
128 off = (int)(sin(aa) * 10 * (1 - p));
129 XCopyArea(disp, fx_ripple_above, WinGetXwin(fx_ripple_win), gc1, 0, yy,
130 WinGetW(VROOT), 1, off,
131 WinGetH(VROOT) - fx_ripple_waterh + y);
138 FX_Ripple_Init(const char *name __UNUSED__)
141 TIMER_ADD(fx_ripple_timer, 0.066, FX_ripple_timeout, NULL);
147 if (fx_ripple_above != None)
148 EFreePixmap(fx_ripple_above);
150 fx_ripple_above = None;
156 TIMER_DEL(fx_ripple_timer);
157 EClearArea(fx_ripple_win, 0, WinGetH(VROOT) - fx_ripple_waterh,
158 WinGetW(VROOT), fx_ripple_waterh);
162 FX_Ripple_Pause(void)
164 static char paused = 0;
173 FX_Ripple_Init(NULL);
181 /****************************** RAIN DROPS **********************************/
183 #define fx_raindrop_size 96
184 #define fx_raindrop_size2 (fx_raindrop_size / 2)
185 #define fx_raindrop_duration 32
186 #define fx_frequency 4
187 #define fx_amplitude 48
188 static Win fx_raindrops_win = NULL;
189 static int fx_raindrops_number = 4;
190 static PixImg *fx_raindrops_draw = NULL;
191 static Timer *fx_raindrops_timer = NULL;
199 static DropContext fx_raindrops[4];
202 FX_raindrops_timeout(void *data __UNUSED__)
204 static GC gc1 = 0, gc = 0;
207 static char first = 1;
208 static char sintab[256];
209 static unsigned char disttab[fx_raindrop_size][fx_raindrop_size];
212 bgeo = DeskGetBackgroundObj(DesksGetCurrent());
214 if (fx_raindrops_win == None)
223 for (i = 0; i < 256; i++)
225 (char)(sin(((double)i) * M_PI_2 * 4 / 256) * fx_amplitude);
226 for (j = 0; j < fx_raindrop_size; j++)
228 for (i = 0; i < fx_raindrop_size; i++)
230 xx = i - fx_raindrop_size2;
231 yy = j - fx_raindrop_size2;
233 (unsigned char)sqrt((double)((xx * xx) + (yy * yy)));
238 fx_raindrops_win = EobjGetWin(bgeo);
245 gcv.subwindow_mode = IncludeInferiors;
246 gc = EXCreateGC(WinGetXwin(fx_raindrops_win), GCSubwindowMode, &gcv);
247 gc1 = EXCreateGC(WinGetXwin(fx_raindrops_win), 0L, &gcv);
250 ECreatePixImg(WinGetXwin(fx_raindrops_win), fx_raindrop_size,
252 if (!fx_raindrops_draw)
255 for (i = 0; i < fx_raindrops_number; i++)
257 fx_raindrops[i].buf =
258 ECreatePixImg(WinGetXwin(fx_raindrops_win), fx_raindrop_size,
260 if (fx_raindrops[i].buf)
261 XShmGetImage(disp, WinGetXwin(fx_raindrops_win),
262 fx_raindrops[i].buf->xim, fx_raindrops[i].x,
263 fx_raindrops[i].y, 0xffffffff);
264 if (!fx_raindrops[i].buf)
269 SET_GC_CLIP(bgeo, gc1);
271 for (i = 0; i < fx_raindrops_number; i++)
273 fx_raindrops[i].count++;
274 if (fx_raindrops[i].count == fx_raindrop_duration)
279 EClearArea(fx_raindrops_win, fx_raindrops[i].x,
280 fx_raindrops[i].y, fx_raindrop_size, fx_raindrop_size);
281 fx_raindrops[i].count = 0;
288 for (j = 0; j < fx_raindrops_number; j++)
291 rand() % (WinGetW(VROOT) - fx_raindrop_size);
293 rand() % (WinGetH(VROOT) - fx_raindrop_size);
294 if (fx_raindrops[i].x < 0)
295 fx_raindrops[i].x = 0;
296 else if (fx_raindrops[i].x >
297 (WinGetW(VROOT) - fx_raindrop_size))
298 fx_raindrops[i].x = WinGetW(VROOT) - fx_raindrop_size;
299 if (fx_raindrops[i].y < 0)
300 fx_raindrops[i].y = 0;
301 else if (fx_raindrops[i].y >
302 (WinGetH(VROOT) - fx_raindrop_size))
303 fx_raindrops[i].y = WinGetH(VROOT) - fx_raindrop_size;
306 if (((fx_raindrops[i].x >= fx_raindrops[j].x)
307 && (fx_raindrops[i].x <
308 fx_raindrops[j].x + fx_raindrop_size)
309 && (fx_raindrops[i].y >= fx_raindrops[j].y)
310 && (fx_raindrops[i].y <
311 fx_raindrops[j].y + fx_raindrop_size))
314 [i].x + fx_raindrop_size >= fx_raindrops[j].x)
315 && (fx_raindrops[i].x + fx_raindrop_size <
316 fx_raindrops[j].x + fx_raindrop_size)
317 && (fx_raindrops[i].y >= fx_raindrops[j].y)
318 && (fx_raindrops[i].y <
319 fx_raindrops[j].y + fx_raindrop_size))
320 || ((fx_raindrops[i].x >= fx_raindrops[j].x)
321 && (fx_raindrops[i].x <
322 fx_raindrops[j].x + fx_raindrop_size)
323 && (fx_raindrops[i].y + fx_raindrop_size >=
325 && (fx_raindrops[i].y + fx_raindrop_size <
326 fx_raindrops[j].y + fx_raindrop_size))
329 [i].x + fx_raindrop_size >= fx_raindrops[j].x)
330 && (fx_raindrops[i].x + fx_raindrop_size <
331 fx_raindrops[j].x + fx_raindrop_size)
332 && (fx_raindrops[i].y + fx_raindrop_size >=
334 && (fx_raindrops[i].y + fx_raindrop_size <
335 fx_raindrops[j].y + fx_raindrop_size)))
340 XShmGetImage(disp, WinGetXwin(fx_raindrops_win),
341 fx_raindrops[i].buf->xim,
342 fx_raindrops[i].x, fx_raindrops[i].y, 0xffffffff);
345 1 + ((fx_raindrops[i].count << 8) / fx_raindrop_duration);
346 for (y = 0; y < fx_raindrop_size; y++)
348 for (x = 0; x < fx_raindrop_size; x++)
352 dist = disttab[x][y];
353 if (dist > fx_raindrop_size2)
354 XPutPixel(fx_raindrops_draw->xim, x, y,
355 XGetPixel(fx_raindrops[i].buf->xim, x, y));
360 percent = 1 + ((dist << 8) / fx_raindrop_size2);
361 if (percent > percent_done)
362 XPutPixel(fx_raindrops_draw->xim, x, y,
363 XGetPixel(fx_raindrops[i].buf->xim, x, y));
367 int phase, divisor, multiplier;
370 ((percent - percent_done) * fx_frequency) & 0xff;
371 xx = x - fx_raindrop_size2;
372 yy = y - fx_raindrop_size2;
373 divisor = 1 + (dist << 8);
375 (int)sintab[phase] * (256 - percent_done);
376 varx = ((-xx) * multiplier) / divisor;
377 vary = ((-yy) * multiplier) / divisor;
382 else if (xx >= fx_raindrop_size)
383 xx = fx_raindrop_size - 1;
386 else if (yy >= fx_raindrop_size)
387 yy = fx_raindrop_size - 1;
388 XPutPixel(fx_raindrops_draw->xim, x, y,
389 XGetPixel(fx_raindrops[i].buf->xim, xx,
395 XShmPutImage(disp, WinGetXwin(fx_raindrops_win), gc1,
396 fx_raindrops_draw->xim, 0, 0,
397 fx_raindrops[i].x, fx_raindrops[i].y, fx_raindrop_size,
398 fx_raindrop_size, False);
406 FX_Raindrops_Init(const char *name __UNUSED__)
410 fx_raindrops_win = None;
411 for (i = 0; i < fx_raindrops_number; i++)
413 fx_raindrops[i].count = rand() % fx_raindrop_duration;
414 fx_raindrops[i].x = rand() % (WinGetW(VROOT) - fx_raindrop_size);
415 fx_raindrops[i].y = rand() % (WinGetH(VROOT) - fx_raindrop_size);
417 TIMER_ADD(fx_raindrops_timer, 0.066, FX_raindrops_timeout, NULL);
421 FX_Raindrops_Desk(void)
423 fx_raindrops_win = None;
427 FX_Raindrops_Quit(void)
431 TIMER_DEL(fx_raindrops_timer);
432 for (i = 0; i < fx_raindrops_number; i++)
434 EClearArea(fx_raindrops_win, fx_raindrops[i].x, fx_raindrops[i].y,
435 fx_raindrop_size, fx_raindrop_size);
436 if (fx_raindrops[i].buf)
437 EDestroyPixImg(fx_raindrops[i].buf);
438 fx_raindrops[i].buf = NULL;
440 if (fx_raindrops_draw)
441 EDestroyPixImg(fx_raindrops_draw);
442 fx_raindrops_draw = NULL;
443 fx_raindrops_win = None;
447 FX_Raindrops_Pause(void)
449 static char paused = 0;
458 FX_Raindrops_Init(NULL);
463 #endif /* E_FX_RAINDROPS */
465 /****************************** WAVES ***************************************/
467 /****************************************************************************/
469 #define FX_WAVE_WATERH 64
470 #define FX_WAVE_WATERW 64
471 #define FX_WAVE_DEPTH 10
472 #define FX_WAVE_GRABH (FX_WAVE_WATERH + FX_WAVE_DEPTH)
473 #define FX_WAVE_CROSSPERIOD 0.42
474 static Pixmap fx_wave_above = None;
475 static Win fx_wave_win = NULL;
476 static int fx_wave_count = 0;
477 static Timer *fx_wave_timer = NULL;
480 FX_Wave_timeout(void *data __UNUSED__)
483 static double incv = 0, inch = 0;
484 static double incx = 0;
486 static GC gc1 = 0, gc = 0;
490 bgeo = DeskGetBackgroundObj(DesksGetCurrent());
492 /* Check to see if we need to create stuff */
497 fx_wave_win = EobjGetWin(bgeo);
500 ECreatePixmap(fx_wave_win, WinGetW(VROOT), FX_WAVE_WATERH * 2, 0);
505 gcv.subwindow_mode = IncludeInferiors;
506 gc = EXCreateGC(WinGetXwin(fx_wave_win), GCSubwindowMode, &gcv);
507 gc1 = EXCreateGC(WinGetXwin(fx_wave_win), 0L, &gcv);
510 /* On the zero, grab the desktop again. */
511 if (fx_wave_count == 0)
513 XCopyArea(disp, WinGetXwin(fx_wave_win), fx_wave_above, gc, 0,
514 WinGetH(VROOT) - (FX_WAVE_WATERH * 3), WinGetW(VROOT),
515 FX_WAVE_WATERH * 2, 0, 0);
518 /* Increment and roll the counter */
520 if (fx_wave_count > 32)
523 /* Increment and roll some other variables */
525 if (incv > (M_PI_2 * 4))
529 if (inch > (M_PI_2 * 4))
533 if (incx > (M_PI_2 * 4))
536 SET_GC_CLIP(bgeo, gc1);
538 /* Copy the area to correct bugs */
539 if (fx_wave_count == 0)
541 XCopyArea(disp, fx_wave_above, WinGetXwin(fx_wave_win), gc1, 0,
542 WinGetH(VROOT) - FX_WAVE_GRABH, WinGetW(VROOT),
543 FX_WAVE_DEPTH * 2, 0, WinGetH(VROOT) - FX_WAVE_GRABH);
546 /* Go through the bottom couple (FX_WAVE_WATERH) lines of the window */
547 for (y = 0; y < FX_WAVE_WATERH; y++)
554 /* Figure out the side-to-side movement */
555 p = (((double)(FX_WAVE_WATERH - y)) / ((double)FX_WAVE_WATERH));
556 a = p * p * 48 + incv;
557 yoff = y + (int)(sin(a) * 7) + 1;
558 yy = (FX_WAVE_WATERH * 2) - yoff;
559 aa = p * p * FX_WAVE_WATERH + inch;
560 off = (int)(sin(aa) * 10 * (1 - p));
562 /* Set up the next part */
565 /* Go through the width of the screen, in block sizes */
566 for (x = 0; x < WinGetW(VROOT); x += FX_WAVE_WATERW)
571 /* Add something to incx2 and roll it */
572 incx2 += FX_WAVE_CROSSPERIOD;
574 if (incx2 > (M_PI_2 * 4))
578 sx = (int)(sin(incx2) * FX_WAVE_DEPTH);
580 /* Display this block */
581 XCopyArea(disp, fx_wave_above, WinGetXwin(fx_wave_win), gc1, x, yy, /* x, y */
582 FX_WAVE_WATERW, 1, /* w, h */
583 off + x, WinGetH(VROOT) - FX_WAVE_WATERH + y + sx /* dx, dy */
592 FX_Waves_Init(const char *name __UNUSED__)
595 TIMER_ADD(fx_wave_timer, 0.066, FX_Wave_timeout, NULL);
601 EFreePixmap(fx_wave_above);
609 TIMER_DEL(fx_wave_timer);
610 EClearArea(fx_wave_win, 0, WinGetH(VROOT) - FX_WAVE_WATERH,
611 WinGetW(VROOT), FX_WAVE_WATERH);
617 static char paused = 0;
631 #if E_FX_IMAGESPINNER
633 /****************************** IMAGESPINNER ********************************/
635 static Win fx_imagespinner_win = NULL;
636 static int fx_imagespinner_count = 3;
637 static char *fx_imagespinner_params = NULL;
638 static Timer *fx_imagespinner_timer = NULL;
641 FX_imagespinner_timeout(void *data __UNUSED__)
646 if (fx_imagespinner_win == None)
648 bgeo = DeskGetBackgroundObj(DesksGetCurrent());
649 fx_imagespinner_win = EobjGetWin(bgeo);
652 #if 0 /* Don't use getword */
654 string = getword(fx_imagespinner_params, fx_imagespinner_count);
657 fx_imagespinner_count = 3;
658 string = getword(fx_imagespinner_params, fx_imagespinner_count);
662 fx_imagespinner_count++;
667 im = ThemeImageLoad(string);
672 EImageGetSize(im, &w, &h);
673 sscanf(fx_imagespinner_params, "%*s %i %i ", &x, &y);
674 x = ((WinGetW(VROOT) * x) >> 10) - ((w * x) >> 10);
675 y = ((WinGetH(VROOT) * y) >> 10) - ((h * y) >> 10);
676 EImageRenderOnDrawable(im, fx_imagespinner_win, None, 0,
687 FX_ImageSpinner_Init(const char *name)
689 fx_imagespinner_count = 3;
690 TIMER_ADD(fx_imagespinner_timer, 0.066, FX_imagespinner_timeout, NULL);
691 fx_imagespinner_params = Estrdup(name);
695 FX_ImageSpinner_Desk(void)
699 bgeo = DeskGetBackgroundObj(DesksGetCurrent());
700 fx_imagespinner_win = EobjGetWin(bgeo);
704 FX_ImageSpinner_Quit(void)
706 TIMER_DEL(fx_imagespinner_timer);
707 EClearArea(fx_imagespinner_win, 0, 0, WinGetW(VROOT), WinGetH(VROOT));
708 Efree(fx_imagespinner_params);
709 fx_imagespinner_params = NULL;
710 fx_imagespinner_win = None;
714 FX_ImageSpinner_Pause(void)
716 static char paused = 0;
720 FX_ImageSpinner_Quit();
725 FX_ImageSpinner_Init(NULL);
730 #endif /* E_FX_IMAGESPINNER */
732 /****************************************************************************/
734 static FXHandler fx_handlers[] = {
736 FX_Ripple_Init, FX_Ripple_Desk, FX_Ripple_Quit, FX_Ripple_Pause,
739 FX_Waves_Init, FX_Waves_Desk, FX_Waves_Quit, FX_Waves_Pause,
741 #if E_FX_RAINDROPS /* FIXME */
743 FX_Raindrops_Init, FX_Raindrops_Desk, FX_Raindrops_Quit,
747 #if E_FX_IMAGESPINNER
749 FX_ImageSpinner_Init, FX_ImageSpinner_Desk, FX_ImageSpinner_Quit,
750 FX_ImageSpinner_Pause,
754 #define N_FX_HANDLERS (sizeof(fx_handlers)/sizeof(FXHandler))
756 /****************************** Effect handlers *****************************/
759 FX_Find(const char *name)
763 for (i = 0; i < N_FX_HANDLERS; i++)
764 if (!strcmp(fx_handlers[i].name, name))
765 return &fx_handlers[i];
771 FX_Op(const char *name, int fx_op)
786 fxh->init_func(name);
812 for (i = 0; i < N_FX_HANDLERS; i++)
814 if (fx_handlers[i].enabled)
816 if (fx_handlers[i].desk_func)
817 fx_handlers[i].desk_func();
827 for (i = 0; i < N_FX_HANDLERS; i++)
829 if (fx_handlers[i].enabled)
831 if (fx_handlers[i].paused)
833 if (fx_handlers[i].pause_func)
834 fx_handlers[i].pause_func();
835 fx_handlers[i].paused = 1;
839 if (fx_handlers[i].pause_func)
840 fx_handlers[i].pause_func();
841 fx_handlers[i].paused = 0;
853 for (i = 0; i < N_FX_HANDLERS; i++)
855 fxh = &fx_handlers[i];
856 if (fxh->enabled && fxh->init_func)
857 fxh->init_func(fxh->name);
862 FX_IsOn(const char *effect)
866 for (i = 0; i < N_FX_HANDLERS; i++)
868 if (!strcmp(fx_handlers[i].name, effect))
870 return fx_handlers[i].enabled;
876 /****************************************************************************/
883 FxSighan(int sig, void *prm __UNUSED__)
890 case ESIGNAL_AREA_SWITCH_START:
891 case ESIGNAL_DESK_SWITCH_START:
893 case ESIGNAL_AREA_SWITCH_DONE:
894 case ESIGNAL_DESK_SWITCH_DONE:
897 case ESIGNAL_ANIMATION_SUSPEND:
898 case ESIGNAL_ANIMATION_RESUME:
905 static char tmp_effect_raindrops;
906 static char tmp_effect_ripples;
907 static char tmp_effect_waves;
910 CB_ConfigureFX(Dialog * d __UNUSED__, int val, void *data __UNUSED__)
914 FX_Op("raindrops", tmp_effect_raindrops ? FX_OP_START : FX_OP_STOP);
915 FX_Op("ripples", tmp_effect_ripples ? FX_OP_START : FX_OP_STOP);
916 FX_Op("waves", tmp_effect_waves ? FX_OP_START : FX_OP_STOP);
922 _DlgFillFx(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__)
926 tmp_effect_raindrops = FX_IsOn("raindrops");
927 tmp_effect_ripples = FX_IsOn("ripples");
928 tmp_effect_waves = FX_IsOn("waves");
930 DialogItemTableSetOptions(table, 1, 0, 0, 0);
933 di = DialogAddItem(table, DITEM_TEXT);
934 DialogItemSetText(di, _("Effects"));
936 di = DialogAddItem(table, DITEM_CHECKBUTTON);
937 DialogItemSetText(di, _("Enable Effect: Raindrops"));
938 DialogItemCheckButtonSetPtr(di, &tmp_effect_raindrops);
940 di = DialogAddItem(table, DITEM_CHECKBUTTON);
941 DialogItemSetText(di, _("Ripples"));
942 DialogItemCheckButtonSetPtr(di, &tmp_effect_ripples);
944 di = DialogAddItem(table, DITEM_CHECKBUTTON);
945 DialogItemSetText(di, _("Waves"));
946 DialogItemCheckButtonSetPtr(di, &tmp_effect_waves);
949 const DialogDef DlgFx = {
952 N_("Special FX Settings"),
955 N_("Enlightenment Special Effects\n" "Settings Dialog\n"),
957 DLG_OAC, CB_ConfigureFX,
959 #endif /* ENABLE_DIALOGS */
962 FxIpc(const char *params)
970 word1[0] = word2[0] = '\0';
971 sscanf(params, "%1000s %1000s", word1, word2);
973 if (!strcmp(word1, "raindrops") || !strcmp(word1, "ripples") ||
974 !strcmp(word1, "waves"))
976 if (!strcmp(word2, ""))
977 FX_Op(word1, FX_OP_TOGGLE);
978 else if (!strcmp(word2, "on"))
979 FX_Op(word1, FX_OP_START);
980 else if (!strcmp(word2, "off"))
981 FX_Op(word1, FX_OP_STOP);
982 else if (!strcmp(word2, "?"))
983 IpcPrintf("%s: %s", word1, FX_IsOn(word1) ? "on" : "off");
985 IpcPrintf("Error: unknown mode specified");
989 static const IpcItem FxIpcArray[] = {
993 "Toggle various effects on/off",
994 " fx <effect> <mode> Set the mode of a particular effect\n"
995 " fx <effect> ?\" Get the current mode\n"
996 "the following effects are available\n"
997 " ripples <on/off> (ripples that act as a water effect on the screen)\n"
998 " waves <on/off> (waves that act as a water effect on the screen)\n"}
1001 #define N_IPC_FUNCS (sizeof(FxIpcArray)/sizeof(IpcItem))
1003 static const CfgItem FxCfgItems[] = {
1004 CFR_ITEM_BOOL(fx_handlers[0].enabled, ripples.enabled, 0),
1005 CFR_ITEM_BOOL(fx_handlers[1].enabled, waves.enabled, 0),
1006 #if E_FX_RAINDROPS /* FIXME */
1007 CFR_ITEM_BOOL(fx_handlers[2].enabled, raindrops.enabled, 0),
1010 #define N_CFG_ITEMS (sizeof(FxCfgItems)/sizeof(CfgItem))
1015 extern const EModule ModEffects;
1016 const EModule ModEffects = {
1019 {N_IPC_FUNCS, FxIpcArray},
1020 {N_CFG_ITEMS, FxCfgItems}