]> Pileus Git - ~andy/gtk/blob - gdk/gdkvisual.c
Initial revision
[~andy/gtk] / gdk / gdkvisual.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <X11/Xlib.h>
19 #include <X11/Xutil.h>
20 #include "gdk.h"
21 #include "gdkprivate.h"
22
23
24 static void  gdk_visual_add            (GdkVisual *visual);
25 static void  gdk_visual_decompose_mask (gulong     mask,
26                                         gint      *shift,
27                                         gint      *prec);
28 static guint gdk_visual_hash           (Visual    *key);
29 static gint  gdk_visual_compare        (Visual    *a,
30                                         Visual    *b);
31
32
33 static GdkVisualPrivate *system_visual;
34 static GdkVisualPrivate *visuals;
35 static gint nvisuals;
36
37 static gint available_depths[4];
38 static gint navailable_depths;
39
40 static GdkVisualType available_types[6];
41 static gint navailable_types;
42
43 static char* visual_names[] =
44 {
45   "static gray",
46   "grayscale",
47   "static color",
48   "pseudo color",
49   "true color",
50   "direct color",
51 };
52
53 static GHashTable *visual_hash = NULL;
54
55 void
56 gdk_visual_init ()
57 {
58   static gint possible_depths[5] = { 32, 24, 16, 15, 8 };
59   static GdkVisualType possible_types[6] =
60     {
61       GDK_VISUAL_DIRECT_COLOR,
62       GDK_VISUAL_TRUE_COLOR,
63       GDK_VISUAL_PSEUDO_COLOR,
64       GDK_VISUAL_STATIC_COLOR,
65       GDK_VISUAL_GRAYSCALE,
66       GDK_VISUAL_STATIC_GRAY
67     };
68
69   static gint npossible_depths = 5;
70   static gint npossible_types = 6;
71
72   XVisualInfo *visual_list;
73   XVisualInfo visual_template;
74   GdkVisualPrivate temp_visual;
75   Visual *default_xvisual;
76   int nxvisuals;
77   int i, j;
78
79   visual_template.screen = gdk_screen;
80   visual_list = XGetVisualInfo (gdk_display, VisualScreenMask, &visual_template, &nxvisuals);
81   visuals = g_new (GdkVisualPrivate, nxvisuals);
82
83   default_xvisual = DefaultVisual (gdk_display, gdk_screen);
84
85   nvisuals = 0;
86   for (i = 0; i < nxvisuals; i++)
87     {
88       if (visual_list[i].depth >= 8)
89         {
90 #ifdef __cplusplus
91           switch (visual_list[i].c_class)
92 #else /* __cplusplus */
93           switch (visual_list[i].class)
94 #endif /* __cplusplus */
95             {
96             case StaticGray:
97               visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_GRAY;
98               break;
99             case GrayScale:
100               visuals[nvisuals].visual.type = GDK_VISUAL_GRAYSCALE;
101               break;
102             case StaticColor:
103               visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
104               break;
105             case PseudoColor:
106               visuals[nvisuals].visual.type = GDK_VISUAL_PSEUDO_COLOR;
107               break;
108             case TrueColor:
109               visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
110               break;
111             case DirectColor:
112               visuals[nvisuals].visual.type = GDK_VISUAL_DIRECT_COLOR;
113               break;
114             }
115
116           visuals[nvisuals].visual.depth = visual_list[i].depth;
117           visuals[nvisuals].visual.byte_order =
118             (ImageByteOrder(gdk_display) == LSBFirst) ?
119             GDK_LSB_FIRST : GDK_MSB_FIRST;
120           visuals[nvisuals].visual.red_mask = visual_list[i].red_mask;
121           visuals[nvisuals].visual.green_mask = visual_list[i].green_mask;
122           visuals[nvisuals].visual.blue_mask = visual_list[i].blue_mask;
123           visuals[nvisuals].visual.colormap_size = visual_list[i].colormap_size;
124           visuals[nvisuals].visual.bits_per_rgb = visual_list[i].bits_per_rgb;
125           visuals[nvisuals].xvisual = visual_list[i].visual;
126
127           if ((visuals[nvisuals].visual.type == GDK_VISUAL_TRUE_COLOR) ||
128               (visuals[nvisuals].visual.type == GDK_VISUAL_DIRECT_COLOR))
129             {
130               gdk_visual_decompose_mask (visuals[nvisuals].visual.red_mask,
131                                          &visuals[nvisuals].visual.red_shift,
132                                          &visuals[nvisuals].visual.red_prec);
133
134               gdk_visual_decompose_mask (visuals[nvisuals].visual.green_mask,
135                                          &visuals[nvisuals].visual.green_shift,
136                                          &visuals[nvisuals].visual.green_prec);
137
138               gdk_visual_decompose_mask (visuals[nvisuals].visual.blue_mask,
139                                          &visuals[nvisuals].visual.blue_shift,
140                                          &visuals[nvisuals].visual.blue_prec);
141             }
142           else
143             {
144               visuals[nvisuals].visual.red_mask = 0;
145               visuals[nvisuals].visual.red_shift = 0;
146               visuals[nvisuals].visual.red_prec = 0;
147
148               visuals[nvisuals].visual.green_mask = 0;
149               visuals[nvisuals].visual.green_shift = 0;
150               visuals[nvisuals].visual.green_prec = 0;
151
152               visuals[nvisuals].visual.blue_mask = 0;
153               visuals[nvisuals].visual.blue_shift = 0;
154               visuals[nvisuals].visual.blue_prec = 0;
155             }
156
157           nvisuals += 1;
158         }
159     }
160
161   XFree (visual_list);
162
163   for (i = 0; i < nvisuals; i++)
164     {
165       for (j = i+1; j < nvisuals; j++)
166         {
167           if (visuals[j].visual.depth >= visuals[i].visual.depth)
168             {
169               if ((visuals[j].visual.depth == 8) && (visuals[i].visual.depth == 8))
170                 {
171                   if (visuals[j].visual.type == GDK_VISUAL_PSEUDO_COLOR)
172                     {
173                       temp_visual = visuals[j];
174                       visuals[j] = visuals[i];
175                       visuals[i] = temp_visual;
176                     }
177                   else if ((visuals[i].visual.type != GDK_VISUAL_PSEUDO_COLOR) &&
178                            visuals[j].visual.type > visuals[i].visual.type)
179                     {
180                       temp_visual = visuals[j];
181                       visuals[j] = visuals[i];
182                       visuals[i] = temp_visual;
183                     }
184                 }
185               else if ((visuals[j].visual.depth > visuals[i].visual.depth) ||
186                        ((visuals[j].visual.depth == visuals[i].visual.depth) &&
187                         (visuals[j].visual.type > visuals[i].visual.type)))
188                 {
189                   temp_visual = visuals[j];
190                   visuals[j] = visuals[i];
191                   visuals[i] = temp_visual;
192                 }
193             }
194         }
195     }
196
197   for (i = 0; i < nvisuals; i++)
198     if (default_xvisual->visualid == visuals[i].xvisual->visualid)
199       {
200         system_visual = &visuals[i];
201         break;
202       }
203
204   if (gdk_debug_level >= 1)
205     for (i = 0; i < nvisuals; i++)
206       g_print ("visual: %s: %d\n",
207                visual_names[visuals[i].visual.type],
208                visuals[i].visual.depth);
209
210   navailable_depths = 0;
211   for (i = 0; i < npossible_depths; i++)
212     {
213       for (j = 0; j < nvisuals; j++)
214         {
215           if (visuals[j].visual.depth == possible_depths[i])
216             {
217               available_depths[navailable_depths++] = visuals[j].visual.depth;
218               break;
219             }
220         }
221     }
222
223   if (navailable_depths == 0)
224     g_error ("unable to find a usable depth");
225
226   navailable_types = 0;
227   for (i = 0; i < npossible_types; i++)
228     {
229       for (j = 0; j < nvisuals; j++)
230         {
231           if (visuals[j].visual.type == possible_types[i])
232             {
233               available_types[navailable_types++] = visuals[j].visual.type;
234               break;
235             }
236         }
237     }
238
239   for (i = 0; i < nvisuals; i++)
240     gdk_visual_add ((GdkVisual*) &visuals[i]);
241
242   if (npossible_types == 0)
243     g_error ("unable to find a usable visual type");
244 }
245
246 GdkVisual*
247 gdk_visual_ref (GdkVisual *visual)
248 {
249   return visual;
250 }
251
252 void
253 gdk_visual_unref (GdkVisual *visual)
254 {
255   return;
256 }
257
258 gint
259 gdk_visual_get_best_depth ()
260 {
261   return available_depths[0];
262 }
263
264 GdkVisualType
265 gdk_visual_get_best_type ()
266 {
267   return available_types[0];
268 }
269
270 GdkVisual*
271 gdk_visual_get_system ()
272 {
273   return ((GdkVisual*) system_visual);
274 }
275
276 GdkVisual*
277 gdk_visual_get_best ()
278 {
279   return ((GdkVisual*) &(visuals[0]));
280 }
281
282 GdkVisual*
283 gdk_visual_get_best_with_depth (gint depth)
284 {
285   GdkVisual *return_val;
286   int i;
287
288   return_val = NULL;
289   for (i = 0; i < nvisuals; i++)
290     if (depth == visuals[i].visual.depth)
291       {
292         return_val = (GdkVisual*) &(visuals[i]);
293         break;
294       }
295
296   return return_val;
297 }
298
299 GdkVisual*
300 gdk_visual_get_best_with_type (GdkVisualType visual_type)
301 {
302   GdkVisual *return_val;
303   int i;
304
305   return_val = NULL;
306   for (i = 0; i < nvisuals; i++)
307     if (visual_type == visuals[i].visual.type)
308       {
309         return_val = (GdkVisual*) &(visuals[i]);
310         break;
311       }
312
313   return return_val;
314 }
315
316 GdkVisual*
317 gdk_visual_get_best_with_both (gint          depth,
318                                GdkVisualType visual_type)
319 {
320   GdkVisual *return_val;
321   int i;
322
323   return_val = NULL;
324   for (i = 0; i < nvisuals; i++)
325     if ((depth == visuals[i].visual.depth) &&
326         (visual_type == visuals[i].visual.type))
327       {
328         return_val = (GdkVisual*) &(visuals[i]);
329         break;
330       }
331
332   return return_val;
333 }
334
335 void
336 gdk_query_depths  (gint **depths,
337                    gint  *count)
338 {
339   *count = navailable_depths;
340   *depths = available_depths;
341 }
342
343 void
344 gdk_query_visual_types (GdkVisualType **visual_types,
345                         gint           *count)
346 {
347   *count = navailable_types;
348   *visual_types = available_types;
349 }
350
351 void
352 gdk_query_visuals (GdkVisual **visual_return,
353                    gint       *count)
354 {
355   *count = nvisuals;
356   *visual_return = (GdkVisual*) visuals;
357 }
358
359
360 GdkVisual*
361 gdk_visual_lookup (Visual *xvisual)
362 {
363   GdkVisual *visual;
364
365   if (!visual_hash)
366     return NULL;
367
368   visual = g_hash_table_lookup (visual_hash, xvisual);
369   return visual;
370 }
371
372 GdkVisual*
373 gdkx_visual_get (VisualID xvisualid)
374 {
375   int i;
376
377   for (i = 0; i < nvisuals; i++)
378     if (xvisualid == visuals[i].xvisual->visualid)
379       return (GdkVisual*) &visuals[i];
380
381   return NULL;
382 }
383
384
385 static void
386 gdk_visual_add (GdkVisual *visual)
387 {
388   GdkVisualPrivate *private;
389
390   if (!visual_hash)
391     visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
392                                     (GCompareFunc) gdk_visual_compare);
393
394   private = (GdkVisualPrivate*) visual;
395
396   g_hash_table_insert (visual_hash, private->xvisual, visual);
397 }
398
399 static void
400 gdk_visual_decompose_mask (gulong  mask,
401                            gint   *shift,
402                            gint   *prec)
403 {
404   *shift = 0;
405   *prec = 0;
406
407   while (!(mask & 0x1))
408     {
409       (*shift)++;
410       mask >>= 1;
411     }
412
413   while (mask & 0x1)
414     {
415       (*prec)++;
416       mask >>= 1;
417     }
418 }
419
420 static guint
421 gdk_visual_hash (Visual *key)
422 {
423   return key->visualid;
424 }
425
426 static gint
427 gdk_visual_compare (Visual *a,
428                     Visual *b)
429 {
430   return (a->visualid == b->visualid);
431 }