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>
33 /* Defines *******************************************************************/
34 #define XTEEVEE_NAME "XTeeVee"
35 #define XTEEVEE_MODE_EXCLUDE 0
36 #define XTEEVEE_MODE_INCLUDE_IMPLICIT 1
37 #define XTEEVEE_MODE_INCLUDE_EXPLICIT 2
38 #define XTEEVEE_ARG_STATIC "static"
39 #define XTEEVEE_ARG_STATIC_SIGNAL "staticSignal"
40 #define XTEEVEE_ARG_ROLL "roll"
41 #define XTEEVEE_ARG_BARS "bars"
42 #define XTEEVEE_ARG_CYCLE "cycle"
43 #define XTEEVEE_ARG_DELAY_MODE "delayMode"
44 #define XTEEVEE_ARG_DELAY_BETWEEN "delayBetween"
45 #define XTEEVEE_STATIC_COLOR_COUNT 6
46 #define XTEEVEE_STATIC_TILE_COUNT 16
49 /* Globals *******************************************************************/
50 char *progclass = XTEEVEE_NAME;
53 "*" XTEEVEE_ARG_STATIC ": true",
54 "*" XTEEVEE_ARG_STATIC_SIGNAL ": 50",
55 "*" XTEEVEE_ARG_ROLL ": true",
56 "*" XTEEVEE_ARG_BARS ": true",
57 "*" XTEEVEE_ARG_CYCLE ": true",
58 "*" XTEEVEE_ARG_DELAY_MODE ": 30",
59 "*" XTEEVEE_ARG_DELAY_BETWEEN ": 3",
62 XrmOptionDescRec options[] =
64 { "-" XTEEVEE_ARG_STATIC,"._" XTEEVEE_ARG_STATIC,XrmoptionNoArg,"true" },
65 { "-no-" XTEEVEE_ARG_STATIC,"." XTEEVEE_ARG_STATIC,XrmoptionNoArg,"false" },
66 { "-" XTEEVEE_ARG_ROLL ,"._" XTEEVEE_ARG_ROLL ,XrmoptionNoArg,"true" },
67 { "-no-" XTEEVEE_ARG_ROLL ,"." XTEEVEE_ARG_ROLL ,XrmoptionNoArg,"false" },
68 { "-" XTEEVEE_ARG_BARS ,"._" XTEEVEE_ARG_BARS ,XrmoptionNoArg,"true" },
69 { "-no-" XTEEVEE_ARG_BARS ,"." XTEEVEE_ARG_BARS ,XrmoptionNoArg,"false" },
70 { "-" XTEEVEE_ARG_CYCLE ,"." XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"true" },
71 { "-no-" XTEEVEE_ARG_CYCLE ,"." XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"false" },
72 { NULL ,NULL ,0 ,NULL }
76 /* Functions *****************************************************************/
78 /* Get the forground pixel ================================================= */
79 void xteevee_FreeColorForeground(Display* x_Disp,XWindowAttributes* x_WinAttr,
84 if (XGetGCValues(x_Disp,x_Gc,GCForeground,&x_GcVal) != 0)
86 XFreeColors(x_Disp,x_WinAttr->colormap,&x_GcVal.foreground,1,
91 /* Static ================================================================== */
92 void xteevee_Static(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
93 time_t hack_Time,Pixmap hack_Pm)
95 GC x_Gc[XTEEVEE_STATIC_COLOR_COUNT];
96 unsigned long pixels[XTEEVEE_STATIC_COLOR_COUNT];
104 Pixmap tile_Tile[XTEEVEE_STATIC_TILE_COUNT];
109 char tile_Used[XTEEVEE_STATIC_TILE_COUNT/2+1];
112 /* Get any extra arguments */
113 signal_Strength = get_integer_resource(XTEEVEE_ARG_STATIC_SIGNAL,
117 color_Color.flags = DoRed|DoGreen|DoBlue;
118 for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
121 color_Color.red = color_Color.green = color_Color.blue =
122 (((double)color_Index+1)/XTEEVEE_STATIC_COLOR_COUNT)*65535;
123 if (!x_WinAttr->colormap ||
124 !XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color))
126 /* NOTE: I have no idea what to do here. Why would
129 pixels[color_Index] = color_Color.pixel;
130 x_GcVal.foreground = color_Color.pixel;
131 x_Gc[color_Index] = XCreateGC(x_Disp,x_Win,GCForeground,
135 /* Build the tiles */
136 for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
139 if (signal_Strength == 0)
141 /* NOTE: Checking XQueryBestTile() returns tiles that
142 are too regular -- you can see patterns
144 tile_Width = (random()%128)+64;
145 tile_Height = (random()%128)+64;
149 tile_Width = x_WinAttr->width;
150 tile_Height = x_WinAttr->height;
152 tile_Tile[tile_Index] = XCreatePixmap(x_Disp,x_Win,tile_Width,
153 tile_Height,x_WinAttr->depth);
154 XCopyArea(x_Disp,hack_Pm,tile_Tile[tile_Index],x_Gc[0],0,0,
155 x_WinAttr->width,x_WinAttr->height,0,0);
157 if (signal_Strength == 0)
161 xim = XCreateImage (x_Disp, x_WinAttr->visual,
163 (x_WinAttr->depth == 1
164 ? XYPixmap : ZPixmap),
170 xim->data = (char *) malloc (xim->bytes_per_line *
176 memcpy (xim->data, orig_bits,
177 xim->bytes_per_line * xim->height);
181 xim = XGetImage (x_Disp, tile_Tile[tile_Index], 0, 0,
182 x_WinAttr->width, x_WinAttr->height, ~0L,
183 (x_WinAttr->depth == 1
184 ? XYPixmap : ZPixmap));
185 orig_bits = (char *) malloc (xim->bytes_per_line *
187 memcpy (orig_bits, xim->data,
188 xim->bytes_per_line * xim->height);
191 for (tile_Y = tile_Height-1;tile_Y >= 0;tile_Y--)
192 for (tile_X = tile_Width-1;tile_X >= 0;tile_X--)
193 if (random()%100 > signal_Strength)
194 XPutPixel(xim,tile_X,tile_Y,
195 pixels[random()%XTEEVEE_STATIC_COLOR_COUNT]);
196 XPutImage(x_Disp,tile_Tile[tile_Index],x_Gc[0],xim,
197 0,0,0,0,x_WinAttr->width,x_WinAttr->height);
200 if (xim) XDestroyImage (xim);
201 if (orig_bits) free (orig_bits);
204 memset(tile_Used,-1,sizeof(tile_Used));
207 hack_Time += time(NULL);
209 while ((time(NULL) < hack_Time) || (hack_Time == 0))
214 tile_Selected = random()%XTEEVEE_STATIC_TILE_COUNT;
215 for (tile_Index = 0;tile_Index < sizeof(tile_Used);
218 if (tile_Used[tile_Index] == tile_Selected)
224 } while (tile_Selected == -1);
225 memmove(tile_Used,tile_Used+1,sizeof(tile_Used)-1);
226 tile_Used[sizeof(tile_Used)-1] = tile_Selected;
229 XSetWindowBackgroundPixmap(x_Disp,x_Win,
230 tile_Tile[tile_Selected]);
231 XClearWindow(x_Disp,x_Win);
234 screenhack_handle_events(x_Disp);
238 /* Free everything */
239 for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
242 xteevee_FreeColorForeground(x_Disp,x_WinAttr,
244 XFreeGC(x_Disp,x_Gc[color_Index]);
247 for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
250 XFreePixmap(x_Disp, tile_Tile[tile_Index]);
254 /* Vertical Roll =========================================================== */
255 void xteevee_Roll(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
256 time_t hack_Time,Pixmap hack_Pm)
262 int blank_Height = x_WinAttr->height/10;
265 x_GcVal.foreground = BlackPixel(x_Disp,0);
266 x_GcVal.subwindow_mode = IncludeInferiors;
267 x_Gc = XCreateGC(x_Disp,x_Win,GCForeground|GCSubwindowMode,&x_GcVal);
272 hack_Time += time(NULL);
274 while ((roll_Y > 0) || ((time(NULL) < hack_Time) || (hack_Time == 0)))
276 if (roll_Y > blank_Height)
278 XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
279 0,x_WinAttr->height-(roll_Y-blank_Height)-1,
280 x_WinAttr->width,roll_Y-blank_Height,
283 XFillRectangle(x_Disp,x_Win,x_Gc,
284 0,roll_Y-blank_Height,
285 x_WinAttr->width,blank_Height);
286 if (roll_Y < x_WinAttr->height)
288 XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
290 x_WinAttr->width,x_WinAttr->height-roll_Y,
294 roll_Y += roll_Speed/2;
299 if (roll_Y > x_WinAttr->height+blank_Height)
307 screenhack_handle_events(x_Disp);
310 /* Free everything */
311 XFreeGC(x_Disp,x_Gc);
314 /* Color-Bars Test Pattern ================================================= */
315 void xteevee_Bars(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
316 time_t hack_Time,Pixmap hack_Pm)
318 draw_colorbars (x_WinAttr->screen, x_WinAttr->visual, x_Win,
320 0, 0, x_WinAttr->width, x_WinAttr->height);
325 hack_Time += time(NULL);
327 while ((time(NULL) < hack_Time) || (hack_Time == 0))
329 screenhack_handle_events(x_Disp);
335 /* Standard XScreenSaver entry point ======================================= */
336 void screenhack(Display* x_Disp,Window x_Win)
338 XWindowAttributes x_WinAttr;
349 int mode_Min = XTEEVEE_MODE_INCLUDE_IMPLICIT;
353 void (*mode_Func)(Display* x_Disp,Window x_Win,
354 XWindowAttributes* x_WinAttr,time_t hack_Time,
359 { XTEEVEE_ARG_STATIC,xteevee_Static,XTEEVEE_MODE_EXCLUDE },
360 { XTEEVEE_ARG_ROLL, xteevee_Roll, XTEEVEE_MODE_EXCLUDE },
361 { XTEEVEE_ARG_BARS, xteevee_Bars, XTEEVEE_MODE_EXCLUDE },
365 /* Grab the screen to give us time to do whatever we want */
366 XGetWindowAttributes(x_Disp,x_Win,&x_WinAttr);
367 load_random_image (x_WinAttr.screen, x_Win, x_Win, NULL, NULL);
369 x_GcVal.subwindow_mode = IncludeInferiors;
370 x_Gc = XCreateGC(x_Disp,x_Win,GCSubwindowMode,&x_GcVal);
371 screen_Pm = XCreatePixmap(x_Disp,x_Win,x_WinAttr.width,
372 x_WinAttr.height,x_WinAttr.depth);
373 XCopyArea(x_Disp,x_Win,screen_Pm,x_Gc,0,0,x_WinAttr.width,
374 x_WinAttr.height,0,0);
376 /* Read the arguments */
377 delay_Mode = get_integer_resource(XTEEVEE_ARG_DELAY_MODE,"Integer");
378 delay_Between = get_integer_resource(XTEEVEE_ARG_DELAY_BETWEEN,
380 if (!get_boolean_resource(XTEEVEE_ARG_CYCLE,"Boolean"))
384 for (mode_Index = 0;mode_Mode[mode_Index].mode_Arg != NULL;
387 if (get_boolean_resource(mode_Mode[mode_Index].mode_Arg,
390 mode_Mode[mode_Index].mode_Flag =
391 XTEEVEE_MODE_INCLUDE_IMPLICIT;
394 sprintf(mode_Arg,"_%s",mode_Mode[mode_Index].mode_Arg);
395 if (get_boolean_resource(mode_Arg,"Boolean") != 0)
397 mode_Mode[mode_Index].mode_Flag =
398 XTEEVEE_MODE_INCLUDE_EXPLICIT;
399 mode_Min = XTEEVEE_MODE_INCLUDE_EXPLICIT;
406 fprintf(stderr,"%s: No modes selected!\n",XTEEVEE_NAME);
410 /* Cycle through various modes */
416 mode_Index = random()%mode_Total;
417 } while (mode_Mode[mode_Index].mode_Flag < mode_Min);
420 mode_Mode[mode_Index].mode_Func(x_Disp,x_Win,&x_WinAttr,
421 delay_Mode,screen_Pm);
423 /* Restore the screen and wait */
424 XCopyArea(x_Disp,screen_Pm,x_Win,x_Gc,0,0,x_WinAttr.width,
425 x_WinAttr.height,0,0);
426 delay_Time = time(NULL)+delay_Between;
427 while (time(NULL) < delay_Time)
429 screenhack_handle_events(x_Disp);