SVN_SILENT made messages (.desktop file)
[kdeartwork.git] / kscreensaver / xsavers / xs_visual.c
blobff20374aad6a493cd25e61f37079b9b8781497dd
1 /* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
2 * by Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
10 * implied warranty.
13 /* This file contains some code for intelligently picking the best visual
14 (where "best" is biased in the direction of either: high color counts;
15 or: having writable color cells...)
18 #include "xs_utils.h"
20 #include "xs_visual.h"
22 #include <X11/Xutil.h>
24 /* extern char *progname; */
27 #ifndef isupper
28 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
29 #endif
30 #ifndef _tolower
31 # define _tolower(c) ((c) - 'A' + 'a')
32 #endif
35 static Visual *pick_best_visual (Screen *, Bool, Bool);
36 static Visual *pick_mono_visual (Screen *);
37 static Visual *pick_best_visual_of_class (Screen *, int);
38 static Visual *id_to_visual (Screen *, int);
39 static Visual *id_to_visual (Screen *screen, int id);
42 #define DEFAULT_VISUAL -1
43 #define BEST_VISUAL -2
44 #define MONO_VISUAL -3
45 #define GRAY_VISUAL -4
46 #define COLOR_VISUAL -5
47 #define SPECIFIC_VISUAL -6
49 Visual *
50 get_visual (Screen *screen, const char *string, Bool prefer_writable_cells,
51 Bool verbose_p)
53 char *v = (string ? strdup(string) : 0);
54 char c, *tmp;
55 int vclass;
56 unsigned long id;
57 Visual *result = 0;
59 if (v)
60 for (tmp = v; *tmp; tmp++)
61 if (isupper (*tmp)) *tmp = _tolower (*tmp);
63 if (!v) vclass = BEST_VISUAL;
64 else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL;
65 else if (!strcmp (v, "best")) vclass = BEST_VISUAL;
66 else if (!strcmp (v, "mono")) vclass = MONO_VISUAL;
67 else if (!strcmp (v, "monochrome")) vclass = MONO_VISUAL;
68 else if (!strcmp (v, "gray")) vclass = GRAY_VISUAL;
69 else if (!strcmp (v, "grey")) vclass = GRAY_VISUAL;
70 else if (!strcmp (v, "color")) vclass = COLOR_VISUAL;
71 else if (!strcmp (v, "staticgray")) vclass = StaticGray;
72 else if (!strcmp (v, "staticcolor")) vclass = StaticColor;
73 else if (!strcmp (v, "truecolor")) vclass = TrueColor;
74 else if (!strcmp (v, "grayscale")) vclass = GrayScale;
75 else if (!strcmp (v, "greyscale")) vclass = GrayScale;
76 else if (!strcmp (v, "pseudocolor")) vclass = PseudoColor;
77 else if (!strcmp (v, "directcolor")) vclass = DirectColor;
78 else if (1 == sscanf (v, " %ld %c", &id, &c)) vclass = SPECIFIC_VISUAL;
79 else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
80 else
82 fprintf (stderr, "%s: unrecognized visual \"%s\".\n", "kscreensaver", v);
83 vclass = DEFAULT_VISUAL;
86 if (vclass == DEFAULT_VISUAL)
87 result = DefaultVisualOfScreen (screen);
88 else if (vclass == BEST_VISUAL)
89 result = pick_best_visual (screen, prefer_writable_cells, False);
90 else if (vclass == MONO_VISUAL)
92 result = pick_mono_visual (screen);
93 if (!result && verbose_p)
94 fprintf (stderr, "%s: no monochrome visuals.\n", "kscreensaver");
96 else if (vclass == GRAY_VISUAL)
98 if (prefer_writable_cells)
99 result = pick_best_visual_of_class (screen, GrayScale);
100 if (!result)
101 result = pick_best_visual_of_class (screen, StaticGray);
102 if (!result)
103 result = pick_best_visual_of_class (screen, GrayScale);
104 if (!result && verbose_p)
105 fprintf (stderr, "%s: no GrayScale or StaticGray visuals.\n",
106 "kscreensaver");
108 else if (vclass == COLOR_VISUAL)
110 int class;
111 /* First see if the default visual will do. */
112 result = DefaultVisualOfScreen (screen);
113 class = visual_class(screen, result);
114 if (class != TrueColor &&
115 class != PseudoColor &&
116 class != DirectColor &&
117 class != StaticColor)
118 result = 0;
119 if (result && visual_depth(screen, result) <= 1)
120 result = 0;
122 /* Else, find the best non-default color visual */
123 if (!result)
124 result = pick_best_visual (screen, prefer_writable_cells, True);
126 if (!result && verbose_p)
127 fprintf (stderr, "%s: no color visuals.\n", "kscreensaver");
129 else if (vclass == SPECIFIC_VISUAL)
131 result = id_to_visual (screen, id);
132 if (!result && verbose_p)
133 fprintf (stderr, "%s: no visual with id 0x%x.\n", "kscreensaver",
134 (unsigned int) id);
136 else
138 Visual *visual = pick_best_visual_of_class (screen, vclass);
139 if (visual)
140 result = visual;
141 else if (verbose_p)
142 fprintf (stderr, "%s: no visual of class %s.\n", "kscreensaver", v);
145 if (v) free (v);
146 return result;
149 Visual *
150 get_visual_resource (Screen *screen, char *name, char *class,
151 Bool prefer_writable_cells)
154 char *string = get_string_resource (name, class);
155 Visual *v = get_visual (screen, string, prefer_writable_cells, True);
156 if (string)
157 free(string);
158 if (v)
159 return v;
160 else
162 return DefaultVisualOfScreen (screen);
166 static Visual *
167 pick_best_visual (Screen *screen, Bool prefer_writable_cells, Bool color_only)
169 Visual *visual;
171 if (!prefer_writable_cells)
173 /* If we don't prefer writable cells, then the "best" visual is the one
174 on which we can allocate the largest range and number of colors.
176 Therefore, a TrueColor visual which is at least 16 bits deep is best.
177 (The assumption here being that a TrueColor of less than 16 bits is
178 really just a PseudoColor visual with a pre-allocated color cube.)
180 The next best thing is a PseudoColor visual of any type. After that
181 come the non-colormappable visuals, and non-color visuals.
183 if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
184 visual_depth (screen, visual) >= 16)
185 return visual;
188 #define TRY_CLASS(CLASS) \
189 if ((visual = pick_best_visual_of_class (screen, CLASS)) && \
190 (!color_only || visual_depth(screen, visual) > 1)) \
191 return visual
192 TRY_CLASS(PseudoColor);
193 TRY_CLASS(TrueColor);
194 TRY_CLASS(DirectColor);
195 TRY_CLASS(StaticColor);
196 if (!color_only)
198 TRY_CLASS(GrayScale);
199 TRY_CLASS(StaticGray);
201 #undef TRY_CLASS
203 visual = DefaultVisualOfScreen (screen);
204 if (!color_only || visual_depth(screen, visual) > 1)
205 return visual;
206 else
207 return 0;
210 static Visual *
211 pick_mono_visual (Screen *screen)
213 Display *dpy = DisplayOfScreen (screen);
214 XVisualInfo vi_in, *vi_out;
215 int out_count;
217 vi_in.depth = 1;
218 vi_in.screen = screen_number (screen);
219 vi_out = XGetVisualInfo (dpy, (VisualDepthMask | VisualScreenMask),
220 &vi_in, &out_count);
221 if (vi_out)
223 Visual *v = (out_count > 0 ? vi_out [0].visual : 0);
224 if (v && vi_out[0].depth != 1)
225 v = 0;
226 XFree ((char *) vi_out);
227 return v;
229 else
230 return 0;
234 static Visual *
235 pick_best_visual_of_class (Screen *screen, int visual_class)
237 /* The best visual of a class is the one which on which we can allocate
238 the largest range and number of colors, which means the one with the
239 greatest depth and number of cells.
241 (But actually, for XDaliClock, all visuals of the same class are
242 probably equivalent - either we have writable cells or we don't.)
244 Display *dpy = DisplayOfScreen (screen);
245 XVisualInfo vi_in, *vi_out;
246 int out_count;
248 vi_in.class = visual_class;
249 vi_in.screen = screen_number (screen);
250 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
251 &vi_in, &out_count);
252 if (vi_out)
254 /* choose the 'best' one, if multiple */
255 int i, best;
256 Visual *visual;
257 for (i = 0, best = 0; i < out_count; i++)
258 /* It's better if it's deeper, or if it's the same depth with
259 more cells (does that ever happen? Well, it could...) */
260 if ((vi_out [i].depth > vi_out [best].depth) ||
261 ((vi_out [i].depth == vi_out [best].depth) &&
262 (vi_out [i].colormap_size > vi_out [best].colormap_size)))
263 best = i;
264 visual = (best < out_count ? vi_out [best].visual : 0);
265 XFree ((char *) vi_out);
266 return visual;
268 else
269 return 0;
272 static Visual *
273 id_to_visual (Screen *screen, int id)
275 Display *dpy = DisplayOfScreen (screen);
276 XVisualInfo vi_in, *vi_out;
277 int out_count;
278 vi_in.screen = screen_number (screen);
279 vi_in.visualid = id;
280 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
281 &vi_in, &out_count);
282 if (vi_out)
284 Visual *v = vi_out[0].visual;
285 XFree ((char *) vi_out);
286 return v;
288 return 0;
292 visual_depth (Screen *screen, Visual *visual)
294 Display *dpy = DisplayOfScreen (screen);
295 XVisualInfo vi_in, *vi_out;
296 int out_count, d;
297 vi_in.screen = screen_number (screen);
298 vi_in.visualid = XVisualIDFromVisual (visual);
299 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
300 &vi_in, &out_count);
301 if (! vi_out) abort ();
302 d = vi_out [0].depth;
303 XFree ((char *) vi_out);
304 return d;
308 #if 0
309 /* You very probably don't want to be using this.
310 Pixmap depth doesn't refer to the depths of pixmaps, but rather, to
311 the depth of protocol-level on-the-wire pixmap data, that is, XImages.
312 To get this info, you should be looking at XImage->bits_per_pixel
313 instead. (And allocating the data for your XImage structures by
314 multiplying ximage->bytes_per_line by ximage->height.)
317 visual_pixmap_depth (Screen *screen, Visual *visual)
319 Display *dpy = DisplayOfScreen (screen);
320 int vdepth = visual_depth (screen, visual);
321 int pdepth = vdepth;
322 int i, pfvc = 0;
323 XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
325 /* Return the first matching depth in the pixmap formats. If there are no
326 matching pixmap formats (which shouldn't be able to happen at all) then
327 return the visual depth instead. */
328 for (i = 0; i < pfvc; i++)
329 if (pfv[i].depth == vdepth)
331 pdepth = pfv[i].bits_per_pixel;
332 break;
334 if (pfv)
335 XFree (pfv);
336 return pdepth;
338 #endif /* 0 */
342 visual_class (Screen *screen, Visual *visual)
344 Display *dpy = DisplayOfScreen (screen);
345 XVisualInfo vi_in, *vi_out;
346 int out_count, c;
347 vi_in.screen = screen_number (screen);
348 vi_in.visualid = XVisualIDFromVisual (visual);
349 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
350 &vi_in, &out_count);
351 if (! vi_out) abort ();
352 c = vi_out [0].class;
353 XFree ((char *) vi_out);
354 return c;
357 Bool
358 has_writable_cells (Screen *screen, Visual *visual)
360 switch (visual_class (screen, visual))
362 case GrayScale: /* Mappable grays. */
363 case PseudoColor: /* Mappable colors. */
364 return True;
365 case StaticGray: /* Fixed grays. */
366 case TrueColor: /* Fixed colors. */
367 case StaticColor: /* (What's the difference again?) */
368 case DirectColor: /* DirectColor visuals are like TrueColor, but have
369 three colormaps - one for each component of RGB.
370 Screw it. */
371 return False;
372 default:
373 abort();
377 void
378 describe_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p)
380 char n[10];
381 Display *dpy = DisplayOfScreen (screen);
382 XVisualInfo vi_in, *vi_out;
383 int out_count;
384 vi_in.screen = screen_number (screen);
385 vi_in.visualid = XVisualIDFromVisual (visual);
386 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
387 &vi_in, &out_count);
388 if (! vi_out) abort ();
389 if (private_cmap_p)
390 sprintf(n, "%3d", vi_out->colormap_size);
391 else
392 strcpy(n, "default");
394 fprintf (f, "0x%02x (%s depth: %2d, cmap: %s)\n",
395 (unsigned int) vi_out->visualid,
396 (vi_out->class == StaticGray ? "StaticGray, " :
397 vi_out->class == StaticColor ? "StaticColor," :
398 vi_out->class == TrueColor ? "TrueColor, " :
399 vi_out->class == GrayScale ? "GrayScale, " :
400 vi_out->class == PseudoColor ? "PseudoColor," :
401 vi_out->class == DirectColor ? "DirectColor," :
402 "UNKNOWN: "),
403 vi_out->depth, n);
404 XFree ((char *) vi_out);
408 screen_number (Screen *screen)
410 Display *dpy = DisplayOfScreen (screen);
411 int i;
412 for (i = 0; i < ScreenCount (dpy); i++)
413 if (ScreenOfDisplay (dpy, i) == screen)
414 return i;
415 abort ();
419 visual_cells (Screen *screen, Visual *visual)
421 Display *dpy = DisplayOfScreen (screen);
422 XVisualInfo vi_in, *vi_out;
423 int out_count, c;
424 vi_in.screen = screen_number (screen);
425 vi_in.visualid = XVisualIDFromVisual (visual);
426 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
427 &vi_in, &out_count);
428 if (! vi_out) abort ();
429 c = vi_out [0].colormap_size;
430 XFree ((char *) vi_out);
431 return c;
434 Visual *
435 find_similar_visual(Screen *screen, Visual *old_visual)
437 Display *dpy = DisplayOfScreen (screen);
438 XVisualInfo vi_in, *vi_out;
439 Visual *result = 0;
440 int out_count;
442 vi_in.screen = screen_number (screen);
443 vi_in.class = visual_class (screen, old_visual);
444 vi_in.depth = visual_depth (screen, old_visual);
446 /* Look for a visual of the same class and depth.
448 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask |
449 VisualDepthMask),
450 &vi_in, &out_count);
451 if (vi_out && out_count > 0)
452 result = vi_out[0].visual;
453 if (vi_out) XFree (vi_out);
454 vi_out = 0;
456 /* Failing that, look for a visual of the same class.
458 if (!result)
460 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask),
461 &vi_in, &out_count);
462 if (vi_out && out_count > 0)
463 result = vi_out[0].visual;
464 if (vi_out) XFree (vi_out);
465 vi_out = 0;
468 /* Failing that, return the default visual. */
469 if (!result)
470 result = DefaultVisualOfScreen (screen);
472 return result;