- s/sprintf/snprintf
[wmaker-crm.git] / wrlib / context.c
blob47848f1d798937d97b1efd1ee6908352674476de
1 /* context.c - X context management
2 *
3 * Raster graphics library
4 *
5 * Copyright (c) 1997, 1998, 1999 Alfredo K. Kojima
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <config.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <X11/Xatom.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
33 #include <math.h>
35 #include "wrasterP.h"
37 #ifdef HAVE_HERMES
38 #include <Hermes/Hermes.h>
39 #endif
41 #include "StdCmap.h"
43 #include "wraster.h"
46 extern void _wraster_change_filter(int type);
49 static Bool bestContext(Display *dpy, int screen_number, RContext *context);
51 static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = {
52 RC_UseSharedMemory|RC_RenderMode|RC_ColorsPerChannel, /* flags */
53 RDitheredRendering, /* render_mode */
54 4, /* colors_per_channel */
55 0,
59 True, /* use_shared_memory */
60 RMitchellFilter,
61 RUseStdColormap
68 * Colormap allocation for PseudoColor visuals:
71 * switch standardColormap:
72 * none:
73 * allocate colors according to colors_per_channel
75 * best/default:
76 * if there's a std colormap defined then use it
78 * else
79 * create a std colormap and set it
86 *----------------------------------------------------------------------
87 * allocateStandardPseudoColor
88 * Creates the internal colormap for PseudoColor, setting the
89 * color values according to the supplied standard colormap.
91 * Returns: -
93 * Side effects: -
95 * Notes: -
96 *----------------------------------------------------------------------
98 static Bool
99 allocateStandardPseudoColor(RContext *ctx, XStandardColormap *stdcmap)
101 int i;
103 ctx->ncolors = stdcmap->red_max * stdcmap->red_mult
104 + stdcmap->green_max * stdcmap->green_mult
105 + stdcmap->blue_max * stdcmap->blue_mult + 1;
107 if (ctx->ncolors <= 1) {
108 RErrorCode = RERR_INTERNAL;
109 puts("wraster: bad standard colormap");
111 return False;
114 ctx->colors = malloc(sizeof(XColor)*ctx->ncolors);
115 if (!ctx->colors) {
116 RErrorCode = RERR_NOMEMORY;
118 return False;
121 ctx->pixels = malloc(sizeof(unsigned long)*ctx->ncolors);
122 if (!ctx->pixels) {
124 free(ctx->colors);
125 ctx->colors = NULL;
127 RErrorCode = RERR_NOMEMORY;
129 return False;
133 #define calc(max,mult) (((i / stdcmap->mult) % \
134 (stdcmap->max + 1)) * 65535) / stdcmap->max
136 for (i = 0; i < ctx->ncolors; i++) {
137 ctx->colors[i].pixel = i + stdcmap->base_pixel;
138 ctx->colors[i].red = calc(red_max, red_mult);
139 ctx->colors[i].green = calc(green_max, green_mult);
140 ctx->colors[i].blue = calc(blue_max, blue_mult);
142 ctx->pixels[i] = ctx->colors[i].pixel;
145 #undef calc
147 return True;
151 static Bool
152 setupStandardColormap(RContext *ctx, Atom property)
154 if (!XmuLookupStandardColormap(ctx->dpy, ctx->screen_number,
155 ctx->visual->visualid,
156 ctx->depth, property,
157 True, True)) {
158 RErrorCode = RERR_STDCMAPFAIL;
160 return False;
162 return True;
173 static Bool
174 allocatePseudoColor(RContext *ctx)
176 XColor *colors;
177 XColor avcolors[256];
178 int avncolors;
179 int i, ncolors, r, g, b;
180 int retries;
181 int cpc = ctx->attribs->colors_per_channel;
183 ncolors = cpc * cpc * cpc;
185 if (ncolors > (1<<ctx->depth)) {
186 /* reduce colormap size */
187 cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
188 ncolors = cpc * cpc * cpc;
191 assert(cpc >= 2 && ncolors <= (1<<ctx->depth));
193 colors = malloc(sizeof(XColor)*ncolors);
194 if (!colors) {
195 RErrorCode = RERR_NOMEMORY;
196 return False;
199 ctx->pixels = malloc(sizeof(unsigned long)*ncolors);
200 if (!ctx->pixels) {
201 free(colors);
202 RErrorCode = RERR_NOMEMORY;
203 return False;
206 i=0;
208 if ((ctx->attribs->flags & RC_GammaCorrection) && ctx->attribs->rgamma > 0
209 && ctx->attribs->ggamma > 0 && ctx->attribs->bgamma > 0) {
210 double rg, gg, bg;
211 double tmp;
213 /* do gamma correction */
214 rg = 1.0/ctx->attribs->rgamma;
215 gg = 1.0/ctx->attribs->ggamma;
216 bg = 1.0/ctx->attribs->bgamma;
217 for (r=0; r<cpc; r++) {
218 for (g=0; g<cpc; g++) {
219 for (b=0; b<cpc; b++) {
220 colors[i].red=(r*0xffff) / (cpc-1);
221 colors[i].green=(g*0xffff) / (cpc-1);
222 colors[i].blue=(b*0xffff) / (cpc-1);
223 colors[i].flags = DoRed|DoGreen|DoBlue;
225 tmp = (double)colors[i].red / 65536.0;
226 colors[i].red = (unsigned short)(65536.0*pow(tmp, rg));
228 tmp = (double)colors[i].green / 65536.0;
229 colors[i].green = (unsigned short)(65536.0*pow(tmp, gg));
231 tmp = (double)colors[i].blue / 65536.0;
232 colors[i].blue = (unsigned short)(65536.0*pow(tmp, bg));
234 i++;
239 } else {
240 for (r=0; r<cpc; r++) {
241 for (g=0; g<cpc; g++) {
242 for (b=0; b<cpc; b++) {
243 colors[i].red=(r*0xffff) / (cpc-1);
244 colors[i].green=(g*0xffff) / (cpc-1);
245 colors[i].blue=(b*0xffff) / (cpc-1);
246 colors[i].flags = DoRed|DoGreen|DoBlue;
247 i++;
252 /* try to allocate the colors */
253 for (i=0; i<ncolors; i++) {
254 if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
255 colors[i].flags = 0; /* failed */
256 } else {
257 colors[i].flags = DoRed|DoGreen|DoBlue;
260 /* try to allocate close values for the colors that couldn't
261 * be allocated before */
262 avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
263 for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
265 XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
267 for (i=0; i<ncolors; i++) {
268 if (colors[i].flags==0) {
269 int j;
270 unsigned long cdiff=0xffffffff, diff;
271 unsigned long closest=0;
273 retries = 2;
275 while (retries--) {
276 /* find closest color */
277 for (j=0; j<avncolors; j++) {
278 r = (colors[i].red - avcolors[i].red)>>8;
279 g = (colors[i].green - avcolors[i].green)>>8;
280 b = (colors[i].blue - avcolors[i].blue)>>8;
281 diff = r*r + g*g + b*b;
282 if (diff<cdiff) {
283 cdiff = diff;
284 closest = j;
287 /* allocate closest color found */
288 colors[i].red = avcolors[closest].red;
289 colors[i].green = avcolors[closest].green;
290 colors[i].blue = avcolors[closest].blue;
291 if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
292 colors[i].flags = DoRed|DoGreen|DoBlue;
293 break; /* succeeded, don't need to retry */
295 #ifdef DEBUG
296 printf("close color allocation failed. Retrying...\n");
297 #endif
302 ctx->colors = colors;
303 ctx->ncolors = ncolors;
305 /* fill the pixels shortcut array */
306 for (i = 0; i < ncolors; i++) {
307 ctx->pixels[i] = ctx->colors[i].pixel;
310 return True;
314 static XColor*
315 allocateGrayScale(RContext *ctx)
317 XColor *colors;
318 XColor avcolors[256];
319 int avncolors;
320 int i, ncolors, r, g, b;
321 int retries;
322 int cpc = ctx->attribs->colors_per_channel;
324 ncolors = cpc * cpc * cpc;
326 if (ctx->vclass == StaticGray) {
327 /* we might as well use all grays */
328 ncolors = 1<<ctx->depth;
329 } else {
330 if ( ncolors > (1<<ctx->depth) ) {
331 /* reduce colormap size */
332 cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
333 ncolors = cpc * cpc * cpc;
336 assert(cpc >= 2 && ncolors <= (1<<ctx->depth));
339 if (ncolors>=256 && ctx->vclass==StaticGray) {
340 /* don't need dithering for 256 levels of gray in StaticGray visual */
341 ctx->attribs->render_mode = RBestMatchRendering;
344 colors = malloc(sizeof(XColor)*ncolors);
345 if (!colors) {
346 RErrorCode = RERR_NOMEMORY;
347 return False;
349 for (i=0; i<ncolors; i++) {
350 colors[i].red=(i*0xffff) / (ncolors-1);
351 colors[i].green=(i*0xffff) / (ncolors-1);
352 colors[i].blue=(i*0xffff) / (ncolors-1);
353 colors[i].flags = DoRed|DoGreen|DoBlue;
355 /* try to allocate the colors */
356 for (i=0; i<ncolors; i++) {
357 #ifdef DEBUG
358 printf("trying:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
359 #endif
360 if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
361 colors[i].flags = 0; /* failed */
362 #ifdef DEBUG
363 printf("failed:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
364 #endif
365 } else {
366 colors[i].flags = DoRed|DoGreen|DoBlue;
367 #ifdef DEBUG
368 printf("success:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
369 #endif
372 /* try to allocate close values for the colors that couldn't
373 * be allocated before */
374 avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
375 for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
377 XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
379 for (i=0; i<ncolors; i++) {
380 if (colors[i].flags==0) {
381 int j;
382 unsigned long cdiff=0xffffffff, diff;
383 unsigned long closest=0;
385 retries = 2;
387 while (retries--) {
388 /* find closest color */
389 for (j=0; j<avncolors; j++) {
390 r = (colors[i].red - avcolors[i].red)>>8;
391 g = (colors[i].green - avcolors[i].green)>>8;
392 b = (colors[i].blue - avcolors[i].blue)>>8;
393 diff = r*r + g*g + b*b;
394 if (diff<cdiff) {
395 cdiff = diff;
396 closest = j;
399 /* allocate closest color found */
400 #ifdef DEBUG
401 printf("best match:%x,%x,%x => %x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue,avcolors[closest].red,avcolors[closest].green,avcolors[closest].blue);
402 #endif
403 colors[i].red = avcolors[closest].red;
404 colors[i].green = avcolors[closest].green;
405 colors[i].blue = avcolors[closest].blue;
406 if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
407 colors[i].flags = DoRed|DoGreen|DoBlue;
408 break; /* succeeded, don't need to retry */
410 #ifdef DEBUG
411 printf("close color allocation failed. Retrying...\n");
412 #endif
416 return colors;
420 static Bool
421 setupPseudoColorColormap(RContext *context)
423 Atom property = 0;
425 if (context->attribs->standard_colormap_mode == RCreateStdColormap) {
426 property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
428 if (!setupStandardColormap(context, property)) {
429 return False;
433 if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) {
434 XStandardColormap *maps;
435 int count, i;
437 if (!property) {
438 property = XInternAtom(context->dpy, "RGB_BEST_MAP", False);
439 if (!XGetRGBColormaps(context->dpy,
440 DefaultRootWindow(context->dpy),
441 &maps, &count, property)) {
442 maps = NULL;
445 if (!maps) {
446 property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
447 if (!XGetRGBColormaps(context->dpy,
448 DefaultRootWindow(context->dpy),
449 &maps, &count, property)) {
450 maps = NULL;
453 } else {
454 if (!XGetRGBColormaps(context->dpy,
455 DefaultRootWindow(context->dpy),
456 &maps, &count, property)) {
457 maps = NULL;
461 if (maps) {
462 int theMap = -1;
464 for (i = 0; i < count; i++) {
465 if (maps[i].visualid == context->visual->visualid) {
466 theMap = i;
467 break;
471 if (theMap < 0) {
472 puts("wrlib: no std cmap found");
475 if (theMap >= 0
476 && allocateStandardPseudoColor(context, &maps[theMap])) {
478 context->std_rgb_map = XAllocStandardColormap();
480 *context->std_rgb_map = maps[theMap];
482 context->cmap = context->std_rgb_map->colormap;
484 XFree(maps);
486 return True;
489 XFree(maps);
493 context->attribs->standard_colormap_mode = RIgnoreStdColormap;
495 /* RIgnoreStdColormap and fallback */
496 return allocatePseudoColor(context);
502 static char*
503 mygetenv(char *var, int scr)
505 char *p;
506 char varname[64];
508 sprintf(varname, "%s%i", var, scr);
509 p = getenv(varname);
510 if (!p) {
511 p = getenv(var);
513 return p;
517 static void
518 gatherconfig(RContext *context, int screen_n)
520 char *ptr;
522 ptr = mygetenv("WRASTER_GAMMA", screen_n);
523 if (ptr) {
524 float g1,g2,g3;
525 if (sscanf(ptr, "%f/%f/%f", &g1, &g2, &g3)!=3
526 || g1<=0.0 || g2<=0.0 || g3<=0.0) {
527 printf("wrlib: invalid value(s) for gamma correction \"%s\"\n",
528 ptr);
529 } else {
530 context->attribs->flags |= RC_GammaCorrection;
531 context->attribs->rgamma = g1;
532 context->attribs->ggamma = g2;
533 context->attribs->bgamma = g3;
536 ptr = mygetenv("WRASTER_COLOR_RESOLUTION", screen_n);
537 if (ptr) {
538 int i;
539 if (sscanf(ptr, "%d", &i)!=1 || i<2 || i>6) {
540 printf("wrlib: invalid value for color resolution \"%s\"\n",ptr);
541 } else {
542 context->attribs->flags |= RC_ColorsPerChannel;
543 context->attribs->colors_per_channel = i;
547 ptr = mygetenv("WRASTER_OPTIMIZE_FOR_SPEED", screen_n);
548 if (ptr) {
549 context->flags.optimize_for_speed = 1;
550 } else {
551 context->flags.optimize_for_speed = 0;
557 static void
558 getColormap(RContext *context, int screen_number)
560 Colormap cmap = None;
561 XStandardColormap *cmaps;
562 int ncmaps, i;
564 if (XGetRGBColormaps(context->dpy,
565 RootWindow(context->dpy, screen_number),
566 &cmaps, &ncmaps, XA_RGB_DEFAULT_MAP)) {
567 for (i=0; i<ncmaps; ++i) {
568 if (cmaps[i].visualid == context->visual->visualid) {
569 cmap = cmaps[i].colormap;
570 break;
573 XFree(cmaps);
575 if (cmap == None) {
576 XColor color;
578 cmap = XCreateColormap(context->dpy,
579 RootWindow(context->dpy, screen_number),
580 context->visual, AllocNone);
582 color.red = color.green = color.blue = 0;
583 XAllocColor(context->dpy, cmap, &color);
584 context->black = color.pixel;
586 color.red = color.green = color.blue = 0xffff;
587 XAllocColor(context->dpy, cmap, &color);
588 context->white = color.pixel;
591 context->cmap = cmap;
595 static int
596 count_offset(unsigned long mask)
598 int i;
600 i=0;
601 while ((mask & 1)==0) {
602 i++;
603 mask = mask >> 1;
605 return i;
609 RContext*
610 RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
612 RContext *context;
613 XGCValues gcv;
616 context = malloc(sizeof(RContext));
617 if (!context) {
618 RErrorCode = RERR_NOMEMORY;
619 return NULL;
621 memset(context, 0, sizeof(RContext));
623 context->dpy = dpy;
625 context->screen_number = screen_number;
627 context->attribs = malloc(sizeof(RContextAttributes));
628 if (!context->attribs) {
629 free(context);
630 RErrorCode = RERR_NOMEMORY;
631 return NULL;
633 if (!attribs)
634 *context->attribs = DEFAULT_CONTEXT_ATTRIBS;
635 else
636 *context->attribs = *attribs;
638 if (!(context->attribs->flags & RC_StandardColormap)) {
639 context->attribs->standard_colormap_mode = RUseStdColormap;
642 if (!(context->attribs->flags & RC_ScalingFilter)) {
643 context->attribs->flags |= RC_ScalingFilter;
644 context->attribs->scaling_filter = RMitchellFilter;
647 /* get configuration from environment variables */
648 gatherconfig(context, screen_number);
649 #ifndef BENCH
650 _wraster_change_filter(context->attribs->scaling_filter);
651 #endif
652 if ((context->attribs->flags & RC_VisualID)) {
653 XVisualInfo *vinfo, templ;
654 int nret;
656 templ.screen = screen_number;
657 templ.visualid = context->attribs->visualid;
658 vinfo = XGetVisualInfo(context->dpy, VisualIDMask|VisualScreenMask,
659 &templ, &nret);
660 if (!vinfo || nret==0) {
661 free(context);
662 RErrorCode = RERR_BADVISUALID;
663 return NULL;
666 if (vinfo[0].visual == DefaultVisual(dpy, screen_number)) {
667 context->attribs->flags |= RC_DefaultVisual;
668 } else {
669 XSetWindowAttributes attr;
670 unsigned long mask;
672 context->visual = vinfo[0].visual;
673 context->depth = vinfo[0].depth;
674 context->vclass = vinfo[0].class;
675 getColormap(context, screen_number);
676 attr.colormap = context->cmap;
677 attr.override_redirect = True;
678 attr.border_pixel = 0;
679 attr.background_pixel = 0;
680 mask = CWBorderPixel|CWColormap|CWOverrideRedirect|CWBackPixel;
681 context->drawable =
682 XCreateWindow(dpy, RootWindow(dpy, screen_number), 1, 1,
683 1, 1, 0, context->depth, CopyFromParent,
684 context->visual, mask, &attr);
685 /* XSetWindowColormap(dpy, context->drawable, attr.colormap);*/
687 XFree(vinfo);
690 /* use default */
691 if (!context->visual) {
692 if ((context->attribs->flags & RC_DefaultVisual)
693 || !bestContext(dpy, screen_number, context)) {
694 context->visual = DefaultVisual(dpy, screen_number);
695 context->depth = DefaultDepth(dpy, screen_number);
696 context->cmap = DefaultColormap(dpy, screen_number);
697 context->drawable = RootWindow(dpy, screen_number);
698 context->black = BlackPixel(dpy, screen_number);
699 context->white = WhitePixel(dpy, screen_number);
700 context->vclass = context->visual->class;
704 gcv.function = GXcopy;
705 gcv.graphics_exposures = False;
706 context->copy_gc = XCreateGC(dpy, context->drawable, GCFunction
707 |GCGraphicsExposures, &gcv);
709 #ifdef HAVE_HERMES
710 context->hermes_data = malloc(sizeof(RHermesData));
711 if (!context->hermes_data) {
712 RErrorCode = RERR_NOMEMORY;
713 free(context);
714 return NULL;
717 Hermes_Init();
719 context->hermes_data->palette = Hermes_PaletteInstance();
721 unsigned long flags = 0;
723 if (context->attribs->render_mode == RDitheredRendering) {
724 flags |= HERMES_CONVERT_DITHER;
726 context->hermes_data->converter = Hermes_ConverterInstance(flags);
728 #endif
730 if (context->vclass == PseudoColor || context->vclass == StaticColor) {
731 if (!setupPseudoColorColormap(context)) {
732 free(context);
733 return NULL;
735 #ifdef HAVE_HERMES
737 int32 palette[256];
738 int i;
740 for (i = 0; i < context->ncolors; i++) {
741 palette[i] = ((context->colors[i].red >> 8) << 16) ||
742 ((context->colors[i].green >> 8) << 8) ||
743 ((context->colors[i].blue >> 8));
746 Hermes_PaletteSet(context->hermes_data->palette, palette);
748 #endif
749 } else if (context->vclass == GrayScale || context->vclass == StaticGray) {
750 context->colors = allocateGrayScale(context);
751 if (!context->colors) {
752 free(context);
753 return NULL;
755 #ifdef HAVE_HERMES
757 int32 palette[256];
758 int i;
760 for (i = 0; i < context->ncolors; i++) {
761 palette[i] = ((context->colors[i].red >> 8) << 16) ||
762 ((context->colors[i].green >> 8) << 8) ||
763 ((context->colors[i].blue >> 8));
766 Hermes_PaletteSet(context->hermes_data->palette, palette);
768 #endif
769 } else if (context->vclass == TrueColor) {
770 /* calc offsets to create a TrueColor pixel */
771 context->red_offset = count_offset(context->visual->red_mask);
772 context->green_offset = count_offset(context->visual->green_mask);
773 context->blue_offset = count_offset(context->visual->blue_mask);
774 /* disable dithering on 24 bits visuals */
775 if (context->depth >= 24)
776 context->attribs->render_mode = RBestMatchRendering;
779 #ifdef HAVE_HERMES
781 #endif
783 /* check avaiability of MIT-SHM */
784 #ifdef XSHM
785 if (!(context->attribs->flags & RC_UseSharedMemory)) {
786 context->attribs->flags |= RC_UseSharedMemory;
787 context->attribs->use_shared_memory = True;
790 if (context->attribs->use_shared_memory) {
791 int major, minor;
792 Bool sharedPixmaps;
794 context->flags.use_shared_pixmap = 0;
796 if (!XShmQueryVersion(context->dpy, &major, &minor, &sharedPixmaps)) {
797 context->attribs->use_shared_memory = False;
798 } else {
799 if (XShmPixmapFormat(context->dpy)==ZPixmap)
800 context->flags.use_shared_pixmap = sharedPixmaps;
803 #endif
805 return context;
809 static Bool
810 bestContext(Display *dpy, int screen_number, RContext *context)
812 XVisualInfo *vinfo=NULL, rvinfo;
813 int best = -1, numvis, i;
814 long flags;
815 XSetWindowAttributes attr;
817 rvinfo.class = TrueColor;
818 rvinfo.screen = screen_number;
819 flags = VisualClassMask | VisualScreenMask;
821 vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
822 if (vinfo) { /* look for a TrueColor, 24-bit or more (pref 24) */
823 for (i=numvis-1, best = -1; i>=0; i--) {
824 if (vinfo[i].depth == 24) best = i;
825 else if (vinfo[i].depth>24 && best<0) best = i;
829 #if 0
830 if (best == -1) { /* look for a DirectColor, 24-bit or more (pref 24) */
831 rvinfo.class = DirectColor;
832 if (vinfo) XFree((char *) vinfo);
833 vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
834 if (vinfo) {
835 for (i=0, best = -1; i<numvis; i++) {
836 if (vinfo[i].depth == 24) best = i;
837 else if (vinfo[i].depth>24 && best<0) best = i;
841 #endif
842 if (best > -1) {
843 context->visual = vinfo[best].visual;
844 context->depth = vinfo[best].depth;
845 context->vclass = vinfo[best].class;
846 getColormap(context, screen_number);
847 attr.colormap = context->cmap;
848 attr.override_redirect = True;
849 attr.border_pixel = 0;
850 context->drawable =
851 XCreateWindow(dpy, RootWindow(dpy, screen_number),
852 1, 1, 1, 1, 0, context->depth,
853 CopyFromParent, context->visual,
854 CWBorderPixel|CWColormap|CWOverrideRedirect, &attr);
855 /* XSetWindowColormap(dpy, context->drawable, context->cmap);*/
857 if (vinfo) XFree((char *) vinfo);
859 if (best < 0)
860 return False;
861 else
862 return True;