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);