http://se.aminet.net/pub/X11/ftp.x.org/contrib/vms/xscreensaver-124.zip
[xscreensaver] / utils / fade.c
1 /* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@mcom.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 #if __STDC__
13 # include <stdlib.h>
14 #endif
15
16 #include <stdio.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xos.h>
19
20 #if __STDC__
21 # define P(x)x
22 #else
23 # define P(x)()
24 #endif
25
26 extern int get_visual_class P((Display *, Visual *));
27 extern void screenhack_usleep P((int));
28 #define usleep screenhack_usleep
29
30 #define MAX_COLORS 4096
31 static XColor orig_colors [MAX_COLORS];
32 static XColor current_colors [MAX_COLORS];
33 static int ncolors;
34
35 Colormap
36 copy_colormap (dpy, cmap, into_cmap)
37      Display *dpy;
38      Colormap cmap, into_cmap;
39 {
40   int i;
41   Screen *screen = DefaultScreenOfDisplay (dpy);
42   Visual *visual = DefaultVisualOfScreen (screen);
43   Window window = RootWindowOfScreen (screen);
44   int vclass = get_visual_class (dpy, visual);
45
46   ncolors = CellsOfScreen (screen);
47
48   /* If this is a colormap on a mono visual, or one with insanely many
49      color cells, bug out. */
50   if (ncolors <= 2 || ncolors > MAX_COLORS)
51     return 0;
52   /* If this is a non-writable visual, bug out. */
53   if (vclass == StaticGray || vclass == StaticColor || vclass == TrueColor)
54     return 0;
55
56   if (! into_cmap)
57     into_cmap = XCreateColormap (dpy, window, visual, AllocAll);
58   if (! cmap)
59     cmap = DefaultColormap (dpy, DefaultScreen (dpy));
60   for (i = 0; i < ncolors; i++)
61     orig_colors [i].pixel = i;
62   XQueryColors (dpy, cmap, orig_colors, ncolors);
63   XStoreColors (dpy, into_cmap, orig_colors, ncolors);
64   return into_cmap;
65 }
66
67 void
68 blacken_colormap (dpy, cmap)
69      Display *dpy;
70      Colormap cmap;
71 {
72   int i;
73   for (i = 0; i < ncolors; i++)
74     {
75       current_colors [i].pixel = i;
76       current_colors [i].red = current_colors [i].green =
77         current_colors [i].blue = 0;
78     }
79   XStoreColors (dpy, cmap, current_colors, ncolors);
80 }
81
82
83 void
84 fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p)
85      Display *dpy;
86      Colormap cmap, cmap2;
87      int seconds, ticks;
88      Bool out_p;
89 {
90   int i;
91   int steps = seconds * ticks;
92   XEvent dummy_event;
93
94   if (! cmap2)
95     return;
96
97   for (i = 0; i < ncolors; i++)
98     orig_colors [i].pixel = i;
99   XQueryColors (dpy, cmap, orig_colors, ncolors);
100   memcpy (current_colors, orig_colors, ncolors * sizeof (XColor));
101
102   for (i = (out_p ? steps : 0);
103        (out_p ? i > 0 : i < steps);
104        (out_p ? i-- : i++))
105     {
106       int j;
107       for (j = 0; j < ncolors; j++)
108         {
109           current_colors[j].red   = orig_colors[j].red   * i / steps;
110           current_colors[j].green = orig_colors[j].green * i / steps;
111           current_colors[j].blue  = orig_colors[j].blue  * i / steps;
112         }
113       XStoreColors (dpy, cmap2, current_colors, ncolors);
114       XSync (dpy, False);
115
116       /* If there is user activity, bug out.
117          We put the event back so that the calling code can notice it too.
118          It would be better to not remove it at all, but that's harder
119          because Xlib has such a non-design for this kind of crap, and
120          in this application it doesn't matter if the events end up out
121          of order, so in the grand unix tradition we say "fuck it" and
122          do something that mostly works for the time being.
123        */
124       if (XCheckMaskEvent (dpy, (KeyPressMask | KeyReleaseMask |
125                                  ButtonPressMask | ButtonReleaseMask |
126                                  PointerMotionMask),
127                            &dummy_event))
128         {
129           XPutBackEvent (dpy, &dummy_event);
130           return;
131         }
132
133       usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */
134     }
135 }
136
137 #if 0
138
139 \f
140 char *progclass = "foo";
141
142 char *defaults [] = {
143   0
144 };
145
146 XrmOptionDescRec options [] = {0};
147 int options_size = 0;
148
149 void
150 screenhack (dpy, w)
151      Display *dpy;
152      Window w;
153 {
154   Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy));
155   Colormap cmap2 = copy_colormap (dpy, cmap, 0);
156
157   int seconds = 1;
158   int ticks = 30 * seconds;
159   int delay = 1;
160
161   while (1)
162     {
163       XSync (dpy, False);
164       XGrabServer (dpy);
165       XInstallColormap (dpy, cmap2);
166       fade_colormap (dpy, cmap, cmap2, seconds, ticks, True);
167       if (delay) sleep (delay);
168       fade_colormap (dpy, cmap, cmap2, seconds, ticks, False);
169       XInstallColormap (dpy, cmap);
170       XUngrabServer (dpy);
171       XSync (dpy, False);
172       if (delay) sleep (delay);
173     }
174 }
175
176 #endif