source: trunk/third/xscreensaver/hacks/xteevee.c @ 15683

Revision 15683, 15.7 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15682, which included commits to RCS files with non-trunk default branches.
Line 
1/*****************************************************************************
2 *                                                                           *
3 * xteevee -- TV good... TV good...                                          *
4 *                                                                           *
5 * Copyright (c) 1999 Greg Knauss (greg@eod.com)                             *
6 *                                                                           *
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      *
13 * implied warranty.                                                         *
14 *                                                                           *
15 *****************************************************************************/
16
17
18/* Changelog *****************************************************************
19
20        1.0.0   19991119        Initial release
21
22*/
23
24
25/* Includes ******************************************************************/
26#include "screenhack.h"
27#include <X11/Xutil.h>
28
29
30/* Defines *******************************************************************/
31#define XTEEVEE_NAME                    "XTeeVee"
32#define XTEEVEE_MODE_EXCLUDE            0
33#define XTEEVEE_MODE_INCLUDE_IMPLICIT   1
34#define XTEEVEE_MODE_INCLUDE_EXPLICIT   2
35#define XTEEVEE_ARG_STATIC              "static"
36#define XTEEVEE_ARG_STATIC_SIGNAL       "staticSignal"
37#define XTEEVEE_ARG_ROLL                "roll"
38#define XTEEVEE_ARG_BARS                "bars"
39#define XTEEVEE_ARG_CYCLE               "cycle"
40#define XTEEVEE_ARG_DELAY_MODE          "delayMode"
41#define XTEEVEE_ARG_DELAY_BETWEEN       "delayBetween"
42#define XTEEVEE_STATIC_COLOR_COUNT      6
43#define XTEEVEE_STATIC_TILE_COUNT       16
44#define XTEEVEE_BARS_COLOR_TOP_COUNT    7
45#define XTEEVEE_BARS_COLOR_BOTTOM_COUNT 5
46
47
48/* Globals *******************************************************************/
49char *progclass  = XTEEVEE_NAME;
50char *defaults[] =
51{
52        "*" XTEEVEE_ARG_STATIC        ": true",
53        "*" XTEEVEE_ARG_STATIC_SIGNAL ": 50",
54        "*" XTEEVEE_ARG_ROLL          ": true",
55        "*" XTEEVEE_ARG_BARS          ": true",
56        "*" XTEEVEE_ARG_CYCLE         ": true",
57        "*" XTEEVEE_ARG_DELAY_MODE    ": 30",
58        "*" XTEEVEE_ARG_DELAY_BETWEEN ": 3",
59        NULL
60};
61XrmOptionDescRec options[] =
62{
63 { "-"    XTEEVEE_ARG_STATIC,"._" XTEEVEE_ARG_STATIC,XrmoptionNoArg,"true" },
64 { "-no-" XTEEVEE_ARG_STATIC,"."  XTEEVEE_ARG_STATIC,XrmoptionNoArg,"false" },
65 { "-"    XTEEVEE_ARG_ROLL  ,"._" XTEEVEE_ARG_ROLL  ,XrmoptionNoArg,"true" },
66 { "-no-" XTEEVEE_ARG_ROLL  ,"."  XTEEVEE_ARG_ROLL  ,XrmoptionNoArg,"false" },
67 { "-"    XTEEVEE_ARG_BARS  ,"._" XTEEVEE_ARG_BARS  ,XrmoptionNoArg,"true" },
68 { "-no-" XTEEVEE_ARG_BARS  ,"."  XTEEVEE_ARG_BARS  ,XrmoptionNoArg,"false" },
69 { "-"    XTEEVEE_ARG_CYCLE ,"."  XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"true" },
70 { "-no-" XTEEVEE_ARG_CYCLE ,"."  XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"false" },
71 { NULL                     ,NULL                   ,0             ,NULL }
72};
73
74
75/* Functions *****************************************************************/
76
77/* Get the forground pixel ================================================= */
78void xteevee_FreeColorForeground(Display* x_Disp,XWindowAttributes* x_WinAttr,
79      GC x_Gc)
80{
81        XGCValues x_GcVal;
82
83        if (XGetGCValues(x_Disp,x_Gc,GCForeground,&x_GcVal) != 0)
84        {
85                XFreeColors(x_Disp,x_WinAttr->colormap,&x_GcVal.foreground,1,
86                 0);
87        }
88}
89
90/* Static ================================================================== */
91void xteevee_Static(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
92      time_t hack_Time,Pixmap hack_Pm)
93{
94        GC        x_Gc[XTEEVEE_STATIC_COLOR_COUNT];
95        unsigned long pixels[XTEEVEE_STATIC_COLOR_COUNT];
96        XImage   *xim = 0;
97        char     *orig_bits = 0;
98        XGCValues x_GcVal;
99        int       signal_Strength;
100        XColor    color_Color;
101        int       color_Index;
102        int       tile_Index;
103        Pixmap    tile_Tile[XTEEVEE_STATIC_TILE_COUNT];
104        int       tile_X;
105        int       tile_Y;
106        int       tile_Width;
107        int       tile_Height;
108        char      tile_Used[XTEEVEE_STATIC_TILE_COUNT/2+1];
109        int       tile_Selected;
110
111        /* Get any extra arguments */
112        signal_Strength = get_integer_resource(XTEEVEE_ARG_STATIC_SIGNAL,
113         "Integer");
114
115        /* Build the GCs */
116        color_Color.flags = DoRed|DoGreen|DoBlue;
117        for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
118         color_Index++)
119        {
120                color_Color.red = color_Color.green = color_Color.blue =
121                 (((double)color_Index+1)/XTEEVEE_STATIC_COLOR_COUNT)*65535;
122                if (XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color) == 0)
123                {
124                        /* NOTE: I have no idea what to do here.  Why would
125                                 this fail? */
126                }
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,
130                 &x_GcVal);
131        }
132
133        /* Build the tiles */
134        for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
135         tile_Index++)
136        {
137                if (signal_Strength == 0)
138                {
139                        /* NOTE: Checking XQueryBestTile() returns tiles that
140                                 are too regular -- you can see patterns
141                                 emerge. */
142                        tile_Width = (random()%128)+64;
143                        tile_Height = (random()%128)+64;
144                }
145                else
146                {
147                        tile_Width = x_WinAttr->width;
148                        tile_Height = x_WinAttr->height;
149                }
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);
154
155                if (signal_Strength == 0)
156                  {
157                    if (!xim)
158                      {
159                        xim = XCreateImage (x_Disp, x_WinAttr->visual,
160                                            x_WinAttr->depth,
161                                            (x_WinAttr->depth == 1
162                                             ? XYPixmap : ZPixmap),
163                                            0, 0,
164                                            x_WinAttr->width,
165                                            x_WinAttr->height,
166                                            8, 0);
167                       
168                        xim->data = (char *) malloc (xim->bytes_per_line *
169                                                     xim->height);
170                      }
171                  }
172                else if (xim)
173                  {
174                    memcpy (xim->data, orig_bits,
175                            xim->bytes_per_line * xim->height);
176                  }
177                else
178                  {
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 *
184                                                 xim->height);
185                    memcpy (orig_bits, xim->data,
186                            xim->bytes_per_line * xim->height);
187                  }
188
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);
196        }
197
198        if (xim) XDestroyImage (xim);
199        if (orig_bits) free (orig_bits);
200
201        /* Go! */
202        memset(tile_Used,-1,sizeof(tile_Used));
203        if (hack_Time > 0)
204        {
205                hack_Time += time(NULL);
206        }
207        while ((time(NULL) < hack_Time) || (hack_Time == 0))
208        {
209                /* Pick a tile */
210                do
211                {
212                        tile_Selected = random()%XTEEVEE_STATIC_TILE_COUNT;
213                        for (tile_Index = 0;tile_Index < sizeof(tile_Used);
214                         tile_Index++)
215                        {
216                                if (tile_Used[tile_Index] == tile_Selected)
217                                {
218                                        tile_Selected = -1;
219                                        break;
220                                }
221                        }
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;
225
226                /* Set it */
227                XSetWindowBackgroundPixmap(x_Disp,x_Win,
228                 tile_Tile[tile_Selected]);
229                XClearWindow(x_Disp,x_Win);
230
231                XSync(x_Disp,0);
232                screenhack_handle_events(x_Disp);
233                usleep(25000);
234        }
235
236        /* Free everything */
237        for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
238         color_Index++)
239        {
240                xteevee_FreeColorForeground(x_Disp,x_WinAttr,
241                 x_Gc[color_Index]);
242                XFreeGC(x_Disp,x_Gc[color_Index]);
243        }
244
245        for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
246         tile_Index++)
247        {
248                XFreePixmap(x_Disp, tile_Tile[tile_Index]);
249        }
250}
251
252/* Vertical Roll =========================================================== */
253void xteevee_Roll(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
254      time_t hack_Time,Pixmap hack_Pm)
255{
256        GC        x_Gc;
257        XGCValues x_GcVal;
258        int       roll_Y = 0;
259        int       roll_Speed = 0;
260        int       blank_Height = x_WinAttr->height/10;
261
262        /* Build the GC */
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);
266
267        /* Go! */
268        if (hack_Time > 0)
269        {
270                hack_Time += time(NULL);
271        }
272        while ((roll_Y > 0) || ((time(NULL) < hack_Time) || (hack_Time == 0)))
273        {
274                if (roll_Y > blank_Height)
275                {
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,
279                         0,0);
280                }
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)
285                {
286                        XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
287                         0,0,
288                         x_WinAttr->width,x_WinAttr->height-roll_Y,
289                         0,roll_Y);
290                }
291
292                roll_Y += roll_Speed/2;
293                if (roll_Speed < 50)
294                {
295                        roll_Speed++;
296                }
297                if (roll_Y > x_WinAttr->height+blank_Height)
298                {
299                        roll_Y = 0;
300                        roll_Speed = 0;
301                }
302
303                XSync(x_Disp,0);
304                sleep(0);
305                screenhack_handle_events(x_Disp);
306        }
307
308        /* Free everything */
309        XFreeGC(x_Disp,x_Gc);
310}
311
312/* Color-Bars Test Pattern ================================================= */
313void xteevee_Bars(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
314      time_t hack_Time,Pixmap hack_Pm)
315{
316        GC        x_GcTop[XTEEVEE_BARS_COLOR_TOP_COUNT];
317        GC        x_GcBottom[XTEEVEE_BARS_COLOR_BOTTOM_COUNT];
318        XGCValues x_GcVal;
319        int       color_Index;
320        XColor    color_Color;
321        char*     color_ColorTop[] =
322        {
323                "grey",
324                "yellow",
325                "light blue",
326                "green",
327                "orange",
328                "red",
329                "purple"
330        };
331        char*     color_ColorBottom[] =
332        {
333                "black",
334                "white",
335                "black",
336                "black",
337                "black"
338        };
339
340        /* Build the GCs */
341        for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_TOP_COUNT;
342         color_Index++)
343        {
344                if (XParseColor(x_Disp,x_WinAttr->colormap,
345                 color_ColorTop[color_Index],&color_Color) == 0)
346                {
347                        /* NOTE: Um, badness? */
348                }
349                if (XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color) == 0)
350                {
351                        /* NOTE: More badness? */
352                }
353                x_GcVal.foreground = color_Color.pixel;
354                x_GcTop[color_Index] =
355                 XCreateGC(x_Disp,x_Win,GCForeground,&x_GcVal);
356        }
357        for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_BOTTOM_COUNT;
358         color_Index++)
359        {
360                if (XParseColor(x_Disp,x_WinAttr->colormap,
361                 color_ColorBottom[color_Index],&color_Color) == 0)
362                {
363                        /* NOTE: Um, badness? */
364                }
365                if (XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color) == 0)
366                {
367                        /* NOTE: More badness? */
368                }
369                x_GcVal.foreground = color_Color.pixel;
370                x_GcBottom[color_Index] =
371                 XCreateGC(x_Disp,x_Win,GCForeground,&x_GcVal);
372        }
373
374        /* Draw color-bar test pattern */
375        XClearWindow(x_Disp,x_Win);
376        for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_TOP_COUNT;
377         color_Index++)
378        {
379                XFillRectangle(x_Disp,x_Win,x_GcTop[color_Index],
380                 ((x_WinAttr->width/XTEEVEE_BARS_COLOR_TOP_COUNT)+1)*
381                 color_Index,
382                 0,
383                 (x_WinAttr->width/XTEEVEE_BARS_COLOR_TOP_COUNT)+1,
384                 (x_WinAttr->height/5)*4);
385        }
386        for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_BOTTOM_COUNT;
387         color_Index++)
388        {
389                XFillRectangle(x_Disp,x_Win,x_GcBottom[color_Index],
390                 ((x_WinAttr->width/XTEEVEE_BARS_COLOR_BOTTOM_COUNT)+1)*
391                 color_Index,
392                 (x_WinAttr->height/5)*4,
393                 (x_WinAttr->width/XTEEVEE_BARS_COLOR_BOTTOM_COUNT)+1,
394                 x_WinAttr->height-(x_WinAttr->height/5)*4);
395        }
396
397        /* Go! */
398        if (hack_Time > 0)
399        {
400                hack_Time += time(NULL);
401        }
402        while ((time(NULL) < hack_Time) || (hack_Time == 0))
403        {
404                screenhack_handle_events(x_Disp);
405                usleep(100000);
406        }
407
408        /* Free everything */
409        for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_TOP_COUNT;
410         color_Index++)
411        {
412                xteevee_FreeColorForeground(x_Disp,x_WinAttr,
413                 x_GcTop[color_Index]);
414                XFreeGC(x_Disp,x_GcTop[color_Index]);
415        }
416        for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_BOTTOM_COUNT;
417         color_Index++)
418        {
419                xteevee_FreeColorForeground(x_Disp,x_WinAttr,
420                 x_GcBottom[color_Index]);
421                XFreeGC(x_Disp,x_GcBottom[color_Index]);
422        }
423}
424
425/* Standard XScreenSaver entry point ======================================= */
426void screenhack(Display* x_Disp,Window x_Win)
427{
428        XWindowAttributes x_WinAttr;
429        GC                x_Gc;
430        XGCValues         x_GcVal;
431        Pixmap            screen_Pm;
432        time_t            delay_Time;
433        int               delay_Mode;
434        int               delay_Between;
435        int               mode_Index;
436        int               mode_Count = 0;
437        int               mode_Total = 0;
438        char              mode_Arg[64+1];
439        int               mode_Min = XTEEVEE_MODE_INCLUDE_IMPLICIT;
440        struct
441        {
442                char* mode_Arg;
443                void  (*mode_Func)(Display* x_Disp,Window x_Win,
444                      XWindowAttributes* x_WinAttr,time_t hack_Time,
445                      Pixmap hack_Pm);
446                int   mode_Flag;
447        } mode_Mode[] =
448        {
449                { XTEEVEE_ARG_STATIC,xteevee_Static,XTEEVEE_MODE_EXCLUDE },
450                { XTEEVEE_ARG_ROLL,  xteevee_Roll,  XTEEVEE_MODE_EXCLUDE },
451                { XTEEVEE_ARG_BARS,  xteevee_Bars,  XTEEVEE_MODE_EXCLUDE },
452                { NULL,              NULL,          -1 }
453        };
454
455        /* Grab the screen to give us time to do whatever we want */
456        XGetWindowAttributes(x_Disp,x_Win,&x_WinAttr);
457        grab_screen_image(x_WinAttr.screen,x_Win);
458        x_GcVal.subwindow_mode = IncludeInferiors;
459        x_Gc = XCreateGC(x_Disp,x_Win,GCSubwindowMode,&x_GcVal);
460        screen_Pm = XCreatePixmap(x_Disp,x_Win,x_WinAttr.width,
461         x_WinAttr.height,x_WinAttr.depth);
462        XCopyArea(x_Disp,x_Win,screen_Pm,x_Gc,0,0,x_WinAttr.width,
463         x_WinAttr.height,0,0);
464
465        /* Read the arguments */
466        delay_Mode = get_integer_resource(XTEEVEE_ARG_DELAY_MODE,"Integer");
467        delay_Between = get_integer_resource(XTEEVEE_ARG_DELAY_BETWEEN,
468         "Integer");
469        if (!get_boolean_resource(XTEEVEE_ARG_CYCLE,"Boolean"))
470        {
471                delay_Mode = 0;
472        }
473        for (mode_Index = 0;mode_Mode[mode_Index].mode_Arg != NULL;
474         mode_Index++)
475        {
476                if (get_boolean_resource(mode_Mode[mode_Index].mode_Arg,
477                 "Boolean") != 0)
478                {
479                        mode_Mode[mode_Index].mode_Flag =
480                         XTEEVEE_MODE_INCLUDE_IMPLICIT;
481                        mode_Count++;
482                }
483                sprintf(mode_Arg,"_%s",mode_Mode[mode_Index].mode_Arg);
484                if (get_boolean_resource(mode_Arg,"Boolean") != 0)
485                {
486                        mode_Mode[mode_Index].mode_Flag =
487                         XTEEVEE_MODE_INCLUDE_EXPLICIT;
488                        mode_Min = XTEEVEE_MODE_INCLUDE_EXPLICIT;
489                        mode_Count++;
490                }
491                mode_Total++;
492        }
493        if (mode_Count == 0)
494        {
495                fprintf(stderr,"%s: No modes selected!\n",XTEEVEE_NAME);
496                return;
497        }
498
499        /* Cycle through various modes */
500        for (;;)
501        {
502                /* Find a mode */
503                do
504                {
505                        mode_Index = random()%mode_Total;
506                } while (mode_Mode[mode_Index].mode_Flag < mode_Min);
507
508                /* Run the hack */
509                mode_Mode[mode_Index].mode_Func(x_Disp,x_Win,&x_WinAttr,
510                 delay_Mode,screen_Pm);
511
512                /* Restore the screen and wait */
513                XCopyArea(x_Disp,screen_Pm,x_Win,x_Gc,0,0,x_WinAttr.width,
514                 x_WinAttr.height,0,0);
515                delay_Time = time(NULL)+delay_Between;
516                while (time(NULL) < delay_Time)
517                {
518                        screenhack_handle_events(x_Disp);
519                        usleep(100000);
520                }
521        }
522}
Note: See TracBrowser for help on using the repository browser.