ftp://ftp.smr.ru/pub/0/FreeBSD/releases/distfiles/xscreensaver-3.16.tar.gz
[xscreensaver] / utils / overlay.c
1 /* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
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 the server's root window contains a SERVER_OVERLAY_VISUALS property,
13    then that identifies the visuals which correspond to the video hardware's
14    overlay planes.  Windows created in these kinds of visuals have the
15    property that one particular pixel value is transparent.
16
17    On my Indy, there are two transparent visuals, one of which is at layer 1,
18    and one of which is at layer 2.  This is apparently the ordering in which
19    they are overlayed (1 being topmost.)  The other difference between them
20    is that the topmost one only has 2 planes, while the next one has 8.
21
22    Rumor has it that SGI, HP, DEC, and IBM all use the same mechanism.
23    Does Sun?
24
25    This code selects the topmost one, regardless of depth.  Maybe that's not
26    the right thing.  Well, in XScreenSaver, we only need to allocate two
27    colors from it (it's only used to display the stderr output, so that the
28    text can overlay the graphics without being obliterated by it.)
29
30    Documentation, such as it is, on SERVER_OVERLAY_VISUALS found on the web:
31
32      http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/server_overlay_visuals.html
33     http://www.xig.com/Pages/Ed-Overlays.html
34
35  */
36
37
38 #include "utils.h"
39
40 #include <X11/Xutil.h>
41 #include <X11/Xproto.h>
42
43 #include "visual.h"
44
45
46 struct overlay_data
47 {
48   CARD32 visual_id;
49   CARD32 transparency;  /* 0: none; 1: pixel; 2: mask (?) */
50   CARD32 value;         /* the transparent pixel */
51   CARD32 layer;         /* -1: underlay; 0: normal; 1: popup; 2: overlay */
52 };
53
54 static int
55 get_overlay_prop (Screen *screen, struct overlay_data **data_ret)
56 {
57   int result;
58   Atom actual_type;
59   int actual_format;
60   unsigned long nitems, bytes_after;
61   struct overlay_data *data = 0;
62   Display *dpy = DisplayOfScreen(screen);
63   Window window = RootWindowOfScreen(screen);
64   Atom XA_SERVER_OVERLAY_VISUALS =
65     XInternAtom (dpy, "SERVER_OVERLAY_VISUALS", False);
66
67   *data_ret = 0;
68   result = XGetWindowProperty (dpy, window, XA_SERVER_OVERLAY_VISUALS,
69                                0, (65536 / sizeof (long)), False, 
70                                XA_SERVER_OVERLAY_VISUALS,
71                                &actual_type, &actual_format,
72                                &nitems, &bytes_after,
73                                (unsigned char **) &data);
74   if (result != Success ||
75       actual_type != XA_SERVER_OVERLAY_VISUALS ||
76       actual_format != 32 ||
77       nitems < 1)
78     {
79       if (data) XFree(data);
80       return 0;
81     }
82   else
83     {
84       *data_ret = data;
85       return nitems / (sizeof(*data) / sizeof(CARD32));
86     }
87 }
88
89
90 Visual *
91 get_overlay_visual (Screen *screen, unsigned long *transparent_pixel_ret)
92 {
93   struct overlay_data *data = 0;
94   int n_visuals = get_overlay_prop (screen, &data);
95   Visual *visual = 0;
96   int depth = 0;
97   unsigned long pixel = 0;
98   unsigned int layer = 0;
99   int i;
100
101   if (data)
102     for (i = 0; i < n_visuals; i++)
103
104       /* Only accept ones that have a transparent pixel. */
105       if (data[i].transparency == 1)
106         {
107           XVisualInfo vi_in, *vi_out;
108           int out_count;
109           vi_in.visualid = data[i].visual_id;
110           vi_out = XGetVisualInfo (DisplayOfScreen(screen), VisualIDMask,
111                                    &vi_in, &out_count);
112           if (vi_out)
113             {
114               /* Prefer the one at the topmost layer; after that, prefer
115                  the one with the greatest depth (most colors.) */
116               if (layer < data[i].layer ||
117                   (layer == data[i].layer &&
118                    depth < vi_out[0].depth))
119                 {
120                   visual = vi_out[0].visual;
121                   depth  = vi_out[0].depth;
122                   layer  = data[i].layer;
123                   pixel  = data[i].value;
124                 }
125               XFree(vi_out);
126             }
127         }
128
129   if (data) XFree(data);
130   if (visual && transparent_pixel_ret)
131     *transparent_pixel_ret = pixel;
132   return visual;
133 }