ftp://ftp.ntnu.no/old/pub/X11/R5contrib/xscreensaver-1.17.tar.gz
[xscreensaver] / utils / fade.c
1 /* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.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 bcopy(from,to,size) memcpy((to),(from),(size))
22 # define bzero(addr,size) memset((addr),0,(size))
23 extern void screenhack_usleep (unsigned long);
24 #else
25 extern void screenhack_usleep ();
26 #endif
27
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   ncolors = CellsOfScreen (DefaultScreenOfDisplay (dpy));
42   if (ncolors <= 2 || ncolors > MAX_COLORS)
43     return 0;
44   if (! into_cmap)
45     into_cmap = XCreateColormap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
46                                  DefaultVisual (dpy, DefaultScreen (dpy)),
47                                  AllocAll);
48   if (! cmap)
49     cmap = DefaultColormap (dpy, DefaultScreen (dpy));
50   for (i = 0; i < ncolors; i++)
51     orig_colors [i].pixel = i;
52   XQueryColors (dpy, cmap, orig_colors, ncolors);
53   XStoreColors (dpy, into_cmap, orig_colors, ncolors);
54   return into_cmap;
55 }
56
57 void
58 blacken_colormap (dpy, cmap)
59      Display *dpy;
60      Colormap cmap;
61 {
62   int i;
63   for (i = 0; i < ncolors; i++)
64     {
65       current_colors [i].pixel = i;
66       current_colors [i].red = current_colors [i].green =
67         current_colors [i].blue = 0;
68     }
69   XStoreColors (dpy, cmap, current_colors, ncolors);
70 }
71
72
73 void
74 fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p)
75      Display *dpy;
76      Colormap cmap, cmap2;
77      int seconds, ticks;
78      Bool out_p;
79 {
80   int i;
81   int steps = seconds * ticks;
82   XEvent dummy_event;
83
84   if (! cmap2)
85     return;
86
87   for (i = 0; i < ncolors; i++)
88     orig_colors [i].pixel = i;
89   XQueryColors (dpy, cmap, orig_colors, ncolors);
90   bcopy (orig_colors, current_colors, ncolors * sizeof (XColor));
91
92   for (i = (out_p ? steps : 0);
93        (out_p ? i > 0 : i < steps);
94        (out_p ? i-- : i++))
95     {
96       int j;
97       for (j = 0; j < ncolors; j++)
98         {
99           current_colors[j].red   = orig_colors[j].red   * i / steps;
100           current_colors[j].green = orig_colors[j].green * i / steps;
101           current_colors[j].blue  = orig_colors[j].blue  * i / steps;
102         }
103       XStoreColors (dpy, cmap2, current_colors, ncolors);
104       XSync (dpy, False);
105
106       /* If there is user activity, bug out.
107          We put the event back so that the calling code can notice it too.
108          It would be better to not remove it at all, but that's harder
109          because Xlib has such a non-design for this kind of crap, and
110          in this application it doesn't matter if the events end up out
111          of order, so in the grand unix tradition we say "fuck it" and
112          do something that mostly works for the time being.
113        */
114       if (XCheckMaskEvent (dpy, (KeyPressMask | KeyReleaseMask |
115                                  ButtonPressMask | ButtonReleaseMask |
116                                  PointerMotionMask),
117                            &dummy_event))
118         {
119           XPutBackEvent (dpy, &dummy_event);
120           return;
121         }
122
123       usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */
124     }
125 }
126
127 #if 0
128
129 \f
130 char *progclass = "foo";
131
132 char *defaults [] = {
133   0
134 };
135
136 XrmOptionDescRec options [] = {0};
137 int options_size = 0;
138
139 void
140 screenhack (dpy, w)
141      Display *dpy;
142      Window w;
143 {
144   Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy));
145   Colormap cmap2 = copy_colormap (dpy, cmap, 0);
146
147   int seconds = 1;
148   int ticks = 30 * seconds;
149   int delay = 1;
150
151   while (1)
152     {
153       XSync (dpy, False);
154       XGrabServer (dpy);
155       XInstallColormap (dpy, cmap2);
156       fade_colormap (dpy, cmap, cmap2, seconds, ticks, True);
157       if (delay) sleep (delay);
158       fade_colormap (dpy, cmap, cmap2, seconds, ticks, False);
159       XInstallColormap (dpy, cmap);
160       XUngrabServer (dpy);
161       XSync (dpy, False);
162       if (delay) sleep (delay);
163     }
164 }
165
166 #endif