ftp://ftp.uniovi.es/pub/X11R6/graphics/misc/lock/xscreensaver-1.22.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 extern int get_visual_class ();
21 extern void screenhack_usleep ();
22 #define usleep screenhack_usleep
23
24 #define MAX_COLORS 4096
25 static XColor orig_colors [MAX_COLORS];
26 static XColor current_colors [MAX_COLORS];
27 static int ncolors;
28
29 Colormap
30 copy_colormap (dpy, cmap, into_cmap)
31      Display *dpy;
32      Colormap cmap, into_cmap;
33 {
34   int i;
35   Screen *screen = DefaultScreenOfDisplay (dpy);
36   Visual *visual = DefaultVisualOfScreen (screen);
37   Window window = RootWindowOfScreen (screen);
38   int vclass = get_visual_class (dpy, visual);
39
40   ncolors = CellsOfScreen (screen);
41
42   /* If this is a colormap on a mono visual, or one with insanely many
43      color cells, bug out. */
44   if (ncolors <= 2 || ncolors > MAX_COLORS)
45     return 0;
46   /* If this is a non-writable visual, bug out. */
47   if (vclass == StaticGray || vclass == StaticColor || vclass == TrueColor)
48     return 0;
49
50   if (! into_cmap)
51     into_cmap = XCreateColormap (dpy, window, visual, AllocAll);
52   if (! cmap)
53     cmap = DefaultColormap (dpy, DefaultScreen (dpy));
54   for (i = 0; i < ncolors; i++)
55     orig_colors [i].pixel = i;
56   XQueryColors (dpy, cmap, orig_colors, ncolors);
57   XStoreColors (dpy, into_cmap, orig_colors, ncolors);
58   return into_cmap;
59 }
60
61 void
62 blacken_colormap (dpy, cmap)
63      Display *dpy;
64      Colormap cmap;
65 {
66   int i;
67   for (i = 0; i < ncolors; i++)
68     {
69       current_colors [i].pixel = i;
70       current_colors [i].red = current_colors [i].green =
71         current_colors [i].blue = 0;
72     }
73   XStoreColors (dpy, cmap, current_colors, ncolors);
74 }
75
76
77 void
78 fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p)
79      Display *dpy;
80      Colormap cmap, cmap2;
81      int seconds, ticks;
82      Bool out_p;
83 {
84   int i;
85   int steps = seconds * ticks;
86   XEvent dummy_event;
87
88   if (! cmap2)
89     return;
90
91   for (i = 0; i < ncolors; i++)
92     orig_colors [i].pixel = i;
93   XQueryColors (dpy, cmap, orig_colors, ncolors);
94   memcpy (current_colors, orig_colors, ncolors * sizeof (XColor));
95
96   for (i = (out_p ? steps : 0);
97        (out_p ? i > 0 : i < steps);
98        (out_p ? i-- : i++))
99     {
100       int j;
101       for (j = 0; j < ncolors; j++)
102         {
103           current_colors[j].red   = orig_colors[j].red   * i / steps;
104           current_colors[j].green = orig_colors[j].green * i / steps;
105           current_colors[j].blue  = orig_colors[j].blue  * i / steps;
106         }
107       XStoreColors (dpy, cmap2, current_colors, ncolors);
108       XSync (dpy, False);
109
110       /* If there is user activity, bug out.
111          We put the event back so that the calling code can notice it too.
112          It would be better to not remove it at all, but that's harder
113          because Xlib has such a non-design for this kind of crap, and
114          in this application it doesn't matter if the events end up out
115          of order, so in the grand unix tradition we say "fuck it" and
116          do something that mostly works for the time being.
117        */
118       if (XCheckMaskEvent (dpy, (KeyPressMask | KeyReleaseMask |
119                                  ButtonPressMask | ButtonReleaseMask |
120                                  PointerMotionMask),
121                            &dummy_event))
122         {
123           XPutBackEvent (dpy, &dummy_event);
124           return;
125         }
126
127       usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */
128     }
129 }
130
131 #if 0
132
133 \f
134 char *progclass = "foo";
135
136 char *defaults [] = {
137   0
138 };
139
140 XrmOptionDescRec options [] = {0};
141 int options_size = 0;
142
143 void
144 screenhack (dpy, w)
145      Display *dpy;
146      Window w;
147 {
148   Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy));
149   Colormap cmap2 = copy_colormap (dpy, cmap, 0);
150
151   int seconds = 1;
152   int ticks = 30 * seconds;
153   int delay = 1;
154
155   while (1)
156     {
157       XSync (dpy, False);
158       XGrabServer (dpy);
159       XInstallColormap (dpy, cmap2);
160       fade_colormap (dpy, cmap, cmap2, seconds, ticks, True);
161       if (delay) sleep (delay);
162       fade_colormap (dpy, cmap, cmap2, seconds, ticks, False);
163       XInstallColormap (dpy, cmap);
164       XUngrabServer (dpy);
165       XSync (dpy, False);
166       if (delay) sleep (delay);
167     }
168 }
169
170 #endif