-/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@mcom.com>
+/* xscreensaver, Copyright (c) 1992-1997 Jamie Zawinski <jwz@netscape.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* implied warranty.
*/
-#if __STDC__
-# include <stdlib.h>
-#endif
+#include "utils.h"
-#include <stdio.h>
-#include <X11/Xlib.h>
-#include <X11/Xos.h>
+#include <sys/time.h> /* for gettimeofday() */
-#if __STDC__
-# define P(x)x
-#else
-# define P(x)()
-#endif
+#ifdef VMS
+# include "vms-gtod.h"
+#endif /* VMS */
-extern int get_visual_class P((Display *, Visual *));
-extern void screenhack_usleep P((int));
-#define usleep screenhack_usleep
+#include "visual.h"
+#include "usleep.h"
+#include "fade.h"
-#define MAX_COLORS 4096
-static XColor orig_colors [MAX_COLORS];
-static XColor current_colors [MAX_COLORS];
-static int ncolors;
Colormap
-copy_colormap (dpy, cmap, into_cmap)
- Display *dpy;
- Colormap cmap, into_cmap;
+copy_colormap (Screen *screen, Visual *visual,
+ Colormap cmap, Colormap into_cmap)
{
int i;
- Screen *screen = DefaultScreenOfDisplay (dpy);
- Visual *visual = DefaultVisualOfScreen (screen);
+ Display *dpy = DisplayOfScreen (screen);
Window window = RootWindowOfScreen (screen);
- int vclass = get_visual_class (dpy, visual);
-
- ncolors = CellsOfScreen (screen);
+ int ncolors = CellsOfScreen (screen);
+ XColor *colors = 0;
/* If this is a colormap on a mono visual, or one with insanely many
color cells, bug out. */
- if (ncolors <= 2 || ncolors > MAX_COLORS)
+ if (ncolors <= 2 || ncolors > 4096)
return 0;
/* If this is a non-writable visual, bug out. */
- if (vclass == StaticGray || vclass == StaticColor || vclass == TrueColor)
+ if (!has_writable_cells (screen, visual))
return 0;
if (! into_cmap)
into_cmap = XCreateColormap (dpy, window, visual, AllocAll);
if (! cmap)
- cmap = DefaultColormap (dpy, DefaultScreen (dpy));
+ cmap = DefaultColormapOfScreen (screen);
+
+ colors = (XColor *) calloc(sizeof(XColor), ncolors);
for (i = 0; i < ncolors; i++)
- orig_colors [i].pixel = i;
- XQueryColors (dpy, cmap, orig_colors, ncolors);
- XStoreColors (dpy, into_cmap, orig_colors, ncolors);
+ colors [i].pixel = i;
+ XQueryColors (dpy, cmap, colors, ncolors);
+ XStoreColors (dpy, into_cmap, colors, ncolors);
+ free (colors);
return into_cmap;
}
+
void
-blacken_colormap (dpy, cmap)
- Display *dpy;
- Colormap cmap;
+blacken_colormap (Screen *screen, Colormap cmap)
{
+ Display *dpy = DisplayOfScreen (screen);
+ int ncolors = CellsOfScreen (screen);
+ XColor *colors;
int i;
+ if (ncolors > 4096)
+ return;
+ colors = (XColor *) calloc(sizeof(XColor), ncolors);
for (i = 0; i < ncolors; i++)
- {
- current_colors [i].pixel = i;
- current_colors [i].red = current_colors [i].green =
- current_colors [i].blue = 0;
- }
- XStoreColors (dpy, cmap, current_colors, ncolors);
+ colors[i].pixel = i;
+ XStoreColors (dpy, cmap, colors, ncolors);
+ free (colors);
}
+/* The business with `cmaps_per_screen' is to fake out the SGI 8-bit video
+ hardware, which is capable of installing multiple (4) colormaps
+ simultaniously. We have to install multiple copies of the same set of
+ colors in order to fill up all the available slots in the hardware color
+ lookup table, so we install an extra N colormaps per screen to make sure
+ that all screens really go black. */
+
void
-fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p)
- Display *dpy;
- Colormap cmap, cmap2;
- int seconds, ticks;
- Bool out_p;
+fade_screens (Display *dpy, Colormap *cmaps,
+ int seconds, int ticks,
+ Bool out_p)
{
- int i;
+ int i, j, k;
int steps = seconds * ticks;
+ long usecs_per_step = (long)(seconds * 1000000) / (long)steps;
XEvent dummy_event;
+ int cmaps_per_screen = 5;
+ int nscreens = ScreenCount(dpy);
+ int ncmaps = nscreens * cmaps_per_screen;
+ static Colormap *fade_cmaps = 0;
+ Bool installed = False;
+ int total_ncolors;
+ XColor *orig_colors, *current_colors, *screen_colors, *orig_screen_colors;
+ struct timeval then, now;
+#ifdef GETTIMEOFDAY_TWO_ARGS
+ struct timezone tzp;
+#endif
- if (! cmap2)
- return;
+ total_ncolors = 0;
+ for (i = 0; i < nscreens; i++)
+ total_ncolors += CellsOfScreen (ScreenOfDisplay(dpy, i));
- for (i = 0; i < ncolors; i++)
- orig_colors [i].pixel = i;
- XQueryColors (dpy, cmap, orig_colors, ncolors);
- memcpy (current_colors, orig_colors, ncolors * sizeof (XColor));
+ orig_colors = (XColor *) calloc(sizeof(XColor), total_ncolors);
+ current_colors = (XColor *) calloc(sizeof(XColor), total_ncolors);
+ /* Get the contents of the colormap we are fading from or to. */
+ screen_colors = orig_colors;
+ for (i = 0; i < nscreens; i++)
+ {
+ int ncolors = CellsOfScreen (ScreenOfDisplay (dpy, i));
+ Colormap cmap = (cmaps ? cmaps[i] : 0);
+ if (!cmap) cmap = DefaultColormap(dpy, i);
+
+ for (j = 0; j < ncolors; j++)
+ screen_colors[j].pixel = j;
+ XQueryColors (dpy, cmap, screen_colors, ncolors);
+
+ screen_colors += ncolors;
+ }
+
+ memcpy (current_colors, orig_colors, total_ncolors * sizeof (XColor));
+
+
+ /* Make the writable colormaps (we keep these around and reuse them.) */
+ if (!fade_cmaps)
+ {
+ fade_cmaps = (Colormap *) calloc(sizeof(Colormap), ncmaps);
+ for (i = 0; i < nscreens; i++)
+ {
+ Visual *v = DefaultVisual(dpy, i);
+ Screen *s = ScreenOfDisplay(dpy, i);
+ if (has_writable_cells (s, v))
+ for (j = 0; j < cmaps_per_screen; j++)
+ fade_cmaps[(i * cmaps_per_screen) + j] =
+ XCreateColormap (dpy, RootWindowOfScreen (s), v, AllocAll);
+ }
+ }
+
+#ifdef GETTIMEOFDAY_TWO_ARGS
+ gettimeofday(&then, &tzp);
+#else
+ gettimeofday(&then);
+#endif
+
+ /* Iterate by steps of the animation... */
for (i = (out_p ? steps : 0);
(out_p ? i > 0 : i < steps);
(out_p ? i-- : i++))
{
- int j;
- for (j = 0; j < ncolors; j++)
+
+ /* For each screen, compute the current value of each color...
+ */
+ orig_screen_colors = orig_colors;
+ screen_colors = current_colors;
+ for (j = 0; j < nscreens; j++)
{
- current_colors[j].red = orig_colors[j].red * i / steps;
- current_colors[j].green = orig_colors[j].green * i / steps;
- current_colors[j].blue = orig_colors[j].blue * i / steps;
+ int ncolors = CellsOfScreen (ScreenOfDisplay (dpy, j));
+ for (k = 0; k < ncolors; k++)
+ {
+ /* This doesn't take into account the relative luminance of the
+ RGB components (0.299, 0.587, and 0.114 at gamma 2.2) but
+ the difference is imperceptible for this application... */
+ screen_colors[k].red = orig_screen_colors[k].red * i / steps;
+ screen_colors[k].green = orig_screen_colors[k].green * i / steps;
+ screen_colors[k].blue = orig_screen_colors[k].blue * i / steps;
+ }
+ screen_colors += ncolors;
+ orig_screen_colors += ncolors;
}
- XStoreColors (dpy, cmap2, current_colors, ncolors);
+
+ /* Put the colors into the maps...
+ */
+ screen_colors = current_colors;
+ for (j = 0; j < nscreens; j++)
+ {
+ int ncolors = CellsOfScreen (ScreenOfDisplay (dpy, j));
+ for (k = 0; k < cmaps_per_screen; k++)
+ {
+ Colormap c = fade_cmaps[j * cmaps_per_screen + k];
+ if (c)
+ XStoreColors (dpy, c, screen_colors, ncolors);
+ }
+ screen_colors += ncolors;
+ }
+
+ /* Put the maps on the screens...
+ (only need to do this the first time through the loop.)
+ */
+ if (!installed)
+ {
+ for (j = 0; j < ncmaps; j++)
+ if (fade_cmaps[j])
+ XInstallColormap (dpy, fade_cmaps[j]);
+ installed = True;
+ }
+
XSync (dpy, False);
- /* If there is user activity, bug out.
+ /* If there is user activity, bug out. (Bug out on keypresses or
+ mouse presses, but not motion, and not release events. Bugging
+ out on motion made the unfade hack be totally useless, I think.)
+
We put the event back so that the calling code can notice it too.
It would be better to not remove it at all, but that's harder
because Xlib has such a non-design for this kind of crap, and
of order, so in the grand unix tradition we say "fuck it" and
do something that mostly works for the time being.
*/
- if (XCheckMaskEvent (dpy, (KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask),
- &dummy_event))
+ if (XCheckMaskEvent (dpy, (KeyPressMask|ButtonPressMask), &dummy_event))
{
XPutBackEvent (dpy, &dummy_event);
- return;
+ goto DONE;
}
- usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */
+#ifdef GETTIMEOFDAY_TWO_ARGS
+ gettimeofday(&now, &tzp);
+#else
+ gettimeofday(&now);
+#endif
+
+ /* If we haven't already used up our alotted time, sleep to avoid
+ changing the colormap too fast. */
+ {
+ long diff = (((now.tv_sec - then.tv_sec) * 1000000) +
+ now.tv_usec - then.tv_usec);
+ then.tv_sec = now.tv_sec;
+ then.tv_usec = now.tv_usec;
+ if (usecs_per_step > diff)
+ usleep (usecs_per_step - diff);
+ }
+ }
+
+ DONE:
+
+ if (orig_colors) free (orig_colors);
+ if (current_colors) free (current_colors);
+
+ /* Now put the original maps back, if we want to end up with them.
+ */
+ if (!out_p)
+ {
+ for (i = 0; i < nscreens; i++)
+ {
+ Colormap cmap = (cmaps ? cmaps[i] : 0);
+ if (!cmap) cmap = DefaultColormap(dpy, i);
+ XInstallColormap (dpy, cmap);
+ }
+
+ /* We've faded to the default cmaps, so we don't need the black maps
+ on stage any more. (We can't uninstall these maps yet if we've
+ faded to black, because that would lead to flicker between when
+ we uninstalled them and when the caller raised its black window.)
+ */
+ for (i = 0; i < ncmaps; i++)
+ if (fade_cmaps[i])
+ {
+ XFreeColormap(dpy, fade_cmaps[i]);
+ fade_cmaps[i] = 0;
+ }
+ free(fade_cmaps);
+ fade_cmaps = 0;
}
}
+\f
#if 0
+#include "screenhack.h"
-\f
char *progclass = "foo";
-
char *defaults [] = {
0
};
Display *dpy;
Window w;
{
- Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy));
- Colormap cmap2 = copy_colormap (dpy, cmap, 0);
-
- int seconds = 1;
- int ticks = 30 * seconds;
+ int seconds = 3;
+ int ticks = 20;
int delay = 1;
while (1)
{
XSync (dpy, False);
- XGrabServer (dpy);
- XInstallColormap (dpy, cmap2);
- fade_colormap (dpy, cmap, cmap2, seconds, ticks, True);
+
+ fprintf(stderr,"out..."); fflush(stderr);
+ fade_screens (dpy, 0, seconds, ticks, True);
+ fprintf(stderr, "done.\n"); fflush(stderr);
+
if (delay) sleep (delay);
- fade_colormap (dpy, cmap, cmap2, seconds, ticks, False);
- XInstallColormap (dpy, cmap);
- XUngrabServer (dpy);
- XSync (dpy, False);
+
+ fprintf(stderr,"in..."); fflush(stderr);
+ fade_screens (dpy, 0, seconds, ticks, False);
+ fprintf(stderr, "done.\n"); fflush(stderr);
+
if (delay) sleep (delay);
}
}