1 /*****************************************************************************
3 * xteevee -- TV good... TV good... *
5 * Copyright (c) 1999 Greg Knauss (greg@eod.com) *
7 * Permission to use, copy, modify, distribute, and sell this software and *
8 * its documentation for any purpose is hereby granted without fee, provided *
9 * that the above copyright notice appear in all copies and that both that *
10 * copyright notice and this permission notice appear in supporting *
11 * documentation. No representations are made about the suitability of this *
12 * software for any purpose. It is provided "as is" without express or *
15 *****************************************************************************/
18 /* Changelog *****************************************************************
20 1.0.0 19991119 Initial release
25 /* Includes ******************************************************************/
26 #include "screenhack.h"
27 #include "colorbars.h"
28 #include <X11/Xutil.h>
31 /* Defines *******************************************************************/
32 #define XTEEVEE_NAME "XTeeVee"
33 #define XTEEVEE_MODE_EXCLUDE 0
34 #define XTEEVEE_MODE_INCLUDE_IMPLICIT 1
35 #define XTEEVEE_MODE_INCLUDE_EXPLICIT 2
36 #define XTEEVEE_ARG_STATIC "static"
37 #define XTEEVEE_ARG_STATIC_SIGNAL "staticSignal"
38 #define XTEEVEE_ARG_ROLL "roll"
39 #define XTEEVEE_ARG_BARS "bars"
40 #define XTEEVEE_ARG_CYCLE "cycle"
41 #define XTEEVEE_ARG_DELAY_MODE "delayMode"
42 #define XTEEVEE_ARG_DELAY_BETWEEN "delayBetween"
43 #define XTEEVEE_STATIC_COLOR_COUNT 6
44 #define XTEEVEE_STATIC_TILE_COUNT 16
47 /* Globals *******************************************************************/
48 char *progclass = XTEEVEE_NAME;
51 "*" XTEEVEE_ARG_STATIC ": true",
52 "*" XTEEVEE_ARG_STATIC_SIGNAL ": 50",
53 "*" XTEEVEE_ARG_ROLL ": true",
54 "*" XTEEVEE_ARG_BARS ": true",
55 "*" XTEEVEE_ARG_CYCLE ": true",
56 "*" XTEEVEE_ARG_DELAY_MODE ": 30",
57 "*" XTEEVEE_ARG_DELAY_BETWEEN ": 3",
60 XrmOptionDescRec options[] =
62 { "-" XTEEVEE_ARG_STATIC,"._" XTEEVEE_ARG_STATIC,XrmoptionNoArg,"true" },
63 { "-no-" XTEEVEE_ARG_STATIC,"." XTEEVEE_ARG_STATIC,XrmoptionNoArg,"false" },
64 { "-" XTEEVEE_ARG_ROLL ,"._" XTEEVEE_ARG_ROLL ,XrmoptionNoArg,"true" },
65 { "-no-" XTEEVEE_ARG_ROLL ,"." XTEEVEE_ARG_ROLL ,XrmoptionNoArg,"false" },
66 { "-" XTEEVEE_ARG_BARS ,"._" XTEEVEE_ARG_BARS ,XrmoptionNoArg,"true" },
67 { "-no-" XTEEVEE_ARG_BARS ,"." XTEEVEE_ARG_BARS ,XrmoptionNoArg,"false" },
68 { "-" XTEEVEE_ARG_CYCLE ,"." XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"true" },
69 { "-no-" XTEEVEE_ARG_CYCLE ,"." XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"false" },
70 { NULL ,NULL ,0 ,NULL }
74 /* Functions *****************************************************************/
76 /* Get the forground pixel ================================================= */
77 void xteevee_FreeColorForeground(Display* x_Disp,XWindowAttributes* x_WinAttr,
82 if (XGetGCValues(x_Disp,x_Gc,GCForeground,&x_GcVal) != 0)
84 XFreeColors(x_Disp,x_WinAttr->colormap,&x_GcVal.foreground,1,
89 /* Static ================================================================== */
90 void xteevee_Static(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
91 time_t hack_Time,Pixmap hack_Pm)
93 GC x_Gc[XTEEVEE_STATIC_COLOR_COUNT];
94 unsigned long pixels[XTEEVEE_STATIC_COLOR_COUNT];
102 Pixmap tile_Tile[XTEEVEE_STATIC_TILE_COUNT];
107 char tile_Used[XTEEVEE_STATIC_TILE_COUNT/2+1];
110 /* Get any extra arguments */
111 signal_Strength = get_integer_resource(XTEEVEE_ARG_STATIC_SIGNAL,
115 color_Color.flags = DoRed|DoGreen|DoBlue;
116 for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
119 color_Color.red = color_Color.green = color_Color.blue =
120 (((double)color_Index+1)/XTEEVEE_STATIC_COLOR_COUNT)*65535;
121 if (!x_WinAttr->colormap ||
122 !XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color))
124 /* NOTE: I have no idea what to do here. Why would
127 pixels[color_Index] = color_Color.pixel;
128 x_GcVal.foreground = color_Color.pixel;
129 x_Gc[color_Index] = XCreateGC(x_Disp,x_Win,GCForeground,
133 /* Build the tiles */
134 for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
137 if (signal_Strength == 0)
139 /* NOTE: Checking XQueryBestTile() returns tiles that
140 are too regular -- you can see patterns
142 tile_Width = (random()%128)+64;
143 tile_Height = (random()%128)+64;
147 tile_Width = x_WinAttr->width;
148 tile_Height = x_WinAttr->height;
150 tile_Tile[tile_Index] = XCreatePixmap(x_Disp,x_Win,tile_Width,
151 tile_Height,x_WinAttr->depth);
152 XCopyArea(x_Disp,hack_Pm,tile_Tile[tile_Index],x_Gc[0],0,0,
153 x_WinAttr->width,x_WinAttr->height,0,0);
155 if (signal_Strength == 0)
159 xim = XCreateImage (x_Disp, x_WinAttr->visual,
161 (x_WinAttr->depth == 1
162 ? XYPixmap : ZPixmap),
168 xim->data = (char *) malloc (xim->bytes_per_line *
174 memcpy (xim->data, orig_bits,
175 xim->bytes_per_line * xim->height);
179 xim = XGetImage (x_Disp, tile_Tile[tile_Index], 0, 0,
180 x_WinAttr->width, x_WinAttr->height, ~0L,
181 (x_WinAttr->depth == 1
182 ? XYPixmap : ZPixmap));
183 orig_bits = (char *) malloc (xim->bytes_per_line *
185 memcpy (orig_bits, xim->data,
186 xim->bytes_per_line * xim->height);
189 for (tile_Y = tile_Height-1;tile_Y >= 0;tile_Y--)
190 for (tile_X = tile_Width-1;tile_X >= 0;tile_X--)
191 if (random()%100 > signal_Strength)
192 XPutPixel(xim,tile_X,tile_Y,
193 pixels[random()%XTEEVEE_STATIC_COLOR_COUNT]);
194 XPutImage(x_Disp,tile_Tile[tile_Index],x_Gc[0],xim,
195 0,0,0,0,x_WinAttr->width,x_WinAttr->height);
198 if (xim) XDestroyImage (xim);
199 if (orig_bits) free (orig_bits);
202 memset(tile_Used,-1,sizeof(tile_Used));
205 hack_Time += time(NULL);
207 while ((time(NULL) < hack_Time) || (hack_Time == 0))
212 tile_Selected = random()%XTEEVEE_STATIC_TILE_COUNT;
213 for (tile_Index = 0;tile_Index < sizeof(tile_Used);
216 if (tile_Used[tile_Index] == tile_Selected)
222 } while (tile_Selected == -1);
223 memmove(tile_Used,tile_Used+1,sizeof(tile_Used)-1);
224 tile_Used[sizeof(tile_Used)-1] = tile_Selected;
227 XSetWindowBackgroundPixmap(x_Disp,x_Win,
228 tile_Tile[tile_Selected]);
229 XClearWindow(x_Disp,x_Win);
232 screenhack_handle_events(x_Disp);
236 /* Free everything */
237 for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
240 xteevee_FreeColorForeground(x_Disp,x_WinAttr,
242 XFreeGC(x_Disp,x_Gc[color_Index]);
245 for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
248 XFreePixmap(x_Disp, tile_Tile[tile_Index]);
252 /* Vertical Roll =========================================================== */
253 void xteevee_Roll(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
254 time_t hack_Time,Pixmap hack_Pm)
260 int blank_Height = x_WinAttr->height/10;
263 x_GcVal.foreground = BlackPixel(x_Disp,0);
264 x_GcVal.subwindow_mode = IncludeInferiors;
265 x_Gc = XCreateGC(x_Disp,x_Win,GCForeground|GCSubwindowMode,&x_GcVal);
270 hack_Time += time(NULL);
272 while ((roll_Y > 0) || ((time(NULL) < hack_Time) || (hack_Time == 0)))
274 if (roll_Y > blank_Height)
276 XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
277 0,x_WinAttr->height-(roll_Y-blank_Height)-1,
278 x_WinAttr->width,roll_Y-blank_Height,
281 XFillRectangle(x_Disp,x_Win,x_Gc,
282 0,roll_Y-blank_Height,
283 x_WinAttr->width,blank_Height);
284 if (roll_Y < x_WinAttr->height)
286 XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
288 x_WinAttr->width,x_WinAttr->height-roll_Y,
292 roll_Y += roll_Speed/2;
297 if (roll_Y > x_WinAttr->height+blank_Height)
305 screenhack_handle_events(x_Disp);
308 /* Free everything */
309 XFreeGC(x_Disp,x_Gc);
312 /* Color-Bars Test Pattern ================================================= */
313 void xteevee_Bars(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
314 time_t hack_Time,Pixmap hack_Pm)
316 draw_colorbars (x_Disp, x_Win, 0, 0, x_WinAttr->width, x_WinAttr->height);
321 hack_Time += time(NULL);
323 while ((time(NULL) < hack_Time) || (hack_Time == 0))
325 screenhack_handle_events(x_Disp);
331 /* Standard XScreenSaver entry point ======================================= */
332 void screenhack(Display* x_Disp,Window x_Win)
334 XWindowAttributes x_WinAttr;
345 int mode_Min = XTEEVEE_MODE_INCLUDE_IMPLICIT;
349 void (*mode_Func)(Display* x_Disp,Window x_Win,
350 XWindowAttributes* x_WinAttr,time_t hack_Time,
355 { XTEEVEE_ARG_STATIC,xteevee_Static,XTEEVEE_MODE_EXCLUDE },
356 { XTEEVEE_ARG_ROLL, xteevee_Roll, XTEEVEE_MODE_EXCLUDE },
357 { XTEEVEE_ARG_BARS, xteevee_Bars, XTEEVEE_MODE_EXCLUDE },
361 /* Grab the screen to give us time to do whatever we want */
362 XGetWindowAttributes(x_Disp,x_Win,&x_WinAttr);
363 grab_screen_image(x_WinAttr.screen,x_Win);
365 x_GcVal.subwindow_mode = IncludeInferiors;
366 x_Gc = XCreateGC(x_Disp,x_Win,GCSubwindowMode,&x_GcVal);
367 screen_Pm = XCreatePixmap(x_Disp,x_Win,x_WinAttr.width,
368 x_WinAttr.height,x_WinAttr.depth);
369 XCopyArea(x_Disp,x_Win,screen_Pm,x_Gc,0,0,x_WinAttr.width,
370 x_WinAttr.height,0,0);
372 /* Read the arguments */
373 delay_Mode = get_integer_resource(XTEEVEE_ARG_DELAY_MODE,"Integer");
374 delay_Between = get_integer_resource(XTEEVEE_ARG_DELAY_BETWEEN,
376 if (!get_boolean_resource(XTEEVEE_ARG_CYCLE,"Boolean"))
380 for (mode_Index = 0;mode_Mode[mode_Index].mode_Arg != NULL;
383 if (get_boolean_resource(mode_Mode[mode_Index].mode_Arg,
386 mode_Mode[mode_Index].mode_Flag =
387 XTEEVEE_MODE_INCLUDE_IMPLICIT;
390 sprintf(mode_Arg,"_%s",mode_Mode[mode_Index].mode_Arg);
391 if (get_boolean_resource(mode_Arg,"Boolean") != 0)
393 mode_Mode[mode_Index].mode_Flag =
394 XTEEVEE_MODE_INCLUDE_EXPLICIT;
395 mode_Min = XTEEVEE_MODE_INCLUDE_EXPLICIT;
402 fprintf(stderr,"%s: No modes selected!\n",XTEEVEE_NAME);
406 /* Cycle through various modes */
412 mode_Index = random()%mode_Total;
413 } while (mode_Mode[mode_Index].mode_Flag < mode_Min);
416 mode_Mode[mode_Index].mode_Func(x_Disp,x_Win,&x_WinAttr,
417 delay_Mode,screen_Pm);
419 /* Restore the screen and wait */
420 XCopyArea(x_Disp,screen_Pm,x_Win,x_Gc,0,0,x_WinAttr.width,
421 x_WinAttr.height,0,0);
422 delay_Time = time(NULL)+delay_Between;
423 while (time(NULL) < delay_Time)
425 screenhack_handle_events(x_Disp);