ftp://ftp.smr.ru/pub/0/FreeBSD/releases/distfiles/xscreensaver-3.16.tar.gz
[xscreensaver] / utils / overlay.c
diff --git a/utils/overlay.c b/utils/overlay.c
new file mode 100644 (file)
index 0000000..7277fd0
--- /dev/null
@@ -0,0 +1,133 @@
+/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+/* If the server's root window contains a SERVER_OVERLAY_VISUALS property,
+   then that identifies the visuals which correspond to the video hardware's
+   overlay planes.  Windows created in these kinds of visuals have the
+   property that one particular pixel value is transparent.
+
+   On my Indy, there are two transparent visuals, one of which is at layer 1,
+   and one of which is at layer 2.  This is apparently the ordering in which
+   they are overlayed (1 being topmost.)  The other difference between them
+   is that the topmost one only has 2 planes, while the next one has 8.
+
+   Rumor has it that SGI, HP, DEC, and IBM all use the same mechanism.
+   Does Sun?
+
+   This code selects the topmost one, regardless of depth.  Maybe that's not
+   the right thing.  Well, in XScreenSaver, we only need to allocate two
+   colors from it (it's only used to display the stderr output, so that the
+   text can overlay the graphics without being obliterated by it.)
+
+   Documentation, such as it is, on SERVER_OVERLAY_VISUALS found on the web:
+
+     http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/server_overlay_visuals.html
+    http://www.xig.com/Pages/Ed-Overlays.html
+
+ */
+
+
+#include "utils.h"
+
+#include <X11/Xutil.h>
+#include <X11/Xproto.h>
+
+#include "visual.h"
+
+
+struct overlay_data
+{
+  CARD32 visual_id;
+  CARD32 transparency; /* 0: none; 1: pixel; 2: mask (?) */
+  CARD32 value;                /* the transparent pixel */
+  CARD32 layer;                /* -1: underlay; 0: normal; 1: popup; 2: overlay */
+};
+
+static int
+get_overlay_prop (Screen *screen, struct overlay_data **data_ret)
+{
+  int result;
+  Atom actual_type;
+  int actual_format;
+  unsigned long nitems, bytes_after;
+  struct overlay_data *data = 0;
+  Display *dpy = DisplayOfScreen(screen);
+  Window window = RootWindowOfScreen(screen);
+  Atom XA_SERVER_OVERLAY_VISUALS =
+    XInternAtom (dpy, "SERVER_OVERLAY_VISUALS", False);
+
+  *data_ret = 0;
+  result = XGetWindowProperty (dpy, window, XA_SERVER_OVERLAY_VISUALS,
+                              0, (65536 / sizeof (long)), False, 
+                              XA_SERVER_OVERLAY_VISUALS,
+                              &actual_type, &actual_format,
+                              &nitems, &bytes_after,
+                              (unsigned char **) &data);
+  if (result != Success ||
+      actual_type != XA_SERVER_OVERLAY_VISUALS ||
+      actual_format != 32 ||
+      nitems < 1)
+    {
+      if (data) XFree(data);
+      return 0;
+    }
+  else
+    {
+      *data_ret = data;
+      return nitems / (sizeof(*data) / sizeof(CARD32));
+    }
+}
+
+
+Visual *
+get_overlay_visual (Screen *screen, unsigned long *transparent_pixel_ret)
+{
+  struct overlay_data *data = 0;
+  int n_visuals = get_overlay_prop (screen, &data);
+  Visual *visual = 0;
+  int depth = 0;
+  unsigned long pixel = 0;
+  unsigned int layer = 0;
+  int i;
+
+  if (data)
+    for (i = 0; i < n_visuals; i++)
+
+      /* Only accept ones that have a transparent pixel. */
+      if (data[i].transparency == 1)
+       {
+         XVisualInfo vi_in, *vi_out;
+         int out_count;
+         vi_in.visualid = data[i].visual_id;
+         vi_out = XGetVisualInfo (DisplayOfScreen(screen), VisualIDMask,
+                                  &vi_in, &out_count);
+         if (vi_out)
+           {
+             /* Prefer the one at the topmost layer; after that, prefer
+                the one with the greatest depth (most colors.) */
+             if (layer < data[i].layer ||
+                 (layer == data[i].layer &&
+                  depth < vi_out[0].depth))
+               {
+                 visual = vi_out[0].visual;
+                 depth  = vi_out[0].depth;
+                 layer  = data[i].layer;
+                 pixel  = data[i].value;
+               }
+             XFree(vi_out);
+           }
+       }
+
+  if (data) XFree(data);
+  if (visual && transparent_pixel_ret)
+    *transparent_pixel_ret = pixel;
+  return visual;
+}