]> Pileus Git - ~andy/gtk/blob - gdk/gdkvisual.c
Added notice to look in AUTHORS and ChangeLog files for a list of changes.
[~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
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include "gdk.h"
30 #include "gdkprivate.h"
31 #include "gdkx.h"
32
33
34 static void  gdk_visual_add            (GdkVisual *visual);
35 static void  gdk_visual_decompose_mask (gulong     mask,
36                                         gint      *shift,
37                                         gint      *prec);
38 static guint gdk_visual_hash           (Visual    *key);
39 static gint  gdk_visual_compare        (Visual    *a,
40                                         Visual    *b);
41
42
43 static GdkVisualPrivate *system_visual;
44 static GdkVisualPrivate *visuals;
45 static gint nvisuals;
46
47 static gint available_depths[7];
48 static gint navailable_depths;
49
50 static GdkVisualType available_types[6];
51 static gint navailable_types;
52
53 #ifdef G_ENABLE_DEBUG
54
55 static const gchar* visual_names[] =
56 {
57   "static gray",
58   "grayscale",
59   "static color",
60   "pseudo color",
61   "true color",
62   "direct color",
63 };
64
65 #endif /* G_ENABLE_DEBUG */
66
67 static GHashTable *visual_hash = NULL;
68
69 void
70 gdk_visual_init (void)
71 {
72   static const gint possible_depths[7] = { 32, 24, 16, 15, 8, 4, 1 };
73   static const GdkVisualType possible_types[6] =
74     {
75       GDK_VISUAL_DIRECT_COLOR,
76       GDK_VISUAL_TRUE_COLOR,
77       GDK_VISUAL_PSEUDO_COLOR,
78       GDK_VISUAL_STATIC_COLOR,
79       GDK_VISUAL_GRAYSCALE,
80       GDK_VISUAL_STATIC_GRAY
81     };
82
83   static const gint npossible_depths = sizeof(possible_depths)/sizeof(gint);
84   static const gint npossible_types = sizeof(possible_types)/sizeof(GdkVisualType);
85
86   XVisualInfo *visual_list;
87   XVisualInfo visual_template;
88   GdkVisualPrivate temp_visual;
89   Visual *default_xvisual;
90   int nxvisuals;
91   int i, j;
92
93   visual_template.screen = gdk_screen;
94   visual_list = XGetVisualInfo (gdk_display, VisualScreenMask, &visual_template, &nxvisuals);
95   visuals = g_new (GdkVisualPrivate, nxvisuals);
96
97   default_xvisual = DefaultVisual (gdk_display, gdk_screen);
98
99   nvisuals = 0;
100   for (i = 0; i < nxvisuals; i++)
101     {
102       if (visual_list[i].depth >= 1)
103         {
104 #ifdef __cplusplus
105           switch (visual_list[i].c_class)
106 #else /* __cplusplus */
107           switch (visual_list[i].class)
108 #endif /* __cplusplus */
109             {
110             case StaticGray:
111               visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_GRAY;
112               break;
113             case GrayScale:
114               visuals[nvisuals].visual.type = GDK_VISUAL_GRAYSCALE;
115               break;
116             case StaticColor:
117               visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
118               break;
119             case PseudoColor:
120               visuals[nvisuals].visual.type = GDK_VISUAL_PSEUDO_COLOR;
121               break;
122             case TrueColor:
123               visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
124               break;
125             case DirectColor:
126               visuals[nvisuals].visual.type = GDK_VISUAL_DIRECT_COLOR;
127               break;
128             }
129
130           visuals[nvisuals].visual.depth = visual_list[i].depth;
131           visuals[nvisuals].visual.byte_order =
132             (ImageByteOrder(gdk_display) == LSBFirst) ?
133             GDK_LSB_FIRST : GDK_MSB_FIRST;
134           visuals[nvisuals].visual.red_mask = visual_list[i].red_mask;
135           visuals[nvisuals].visual.green_mask = visual_list[i].green_mask;
136           visuals[nvisuals].visual.blue_mask = visual_list[i].blue_mask;
137           visuals[nvisuals].visual.colormap_size = visual_list[i].colormap_size;
138           visuals[nvisuals].visual.bits_per_rgb = visual_list[i].bits_per_rgb;
139           visuals[nvisuals].xvisual = visual_list[i].visual;
140
141           if ((visuals[nvisuals].visual.type == GDK_VISUAL_TRUE_COLOR) ||
142               (visuals[nvisuals].visual.type == GDK_VISUAL_DIRECT_COLOR))
143             {
144               gdk_visual_decompose_mask (visuals[nvisuals].visual.red_mask,
145                                          &visuals[nvisuals].visual.red_shift,
146                                          &visuals[nvisuals].visual.red_prec);
147
148               gdk_visual_decompose_mask (visuals[nvisuals].visual.green_mask,
149                                          &visuals[nvisuals].visual.green_shift,
150                                          &visuals[nvisuals].visual.green_prec);
151
152               gdk_visual_decompose_mask (visuals[nvisuals].visual.blue_mask,
153                                          &visuals[nvisuals].visual.blue_shift,
154                                          &visuals[nvisuals].visual.blue_prec);
155             }
156           else
157             {
158               visuals[nvisuals].visual.red_mask = 0;
159               visuals[nvisuals].visual.red_shift = 0;
160               visuals[nvisuals].visual.red_prec = 0;
161
162               visuals[nvisuals].visual.green_mask = 0;
163               visuals[nvisuals].visual.green_shift = 0;
164               visuals[nvisuals].visual.green_prec = 0;
165
166               visuals[nvisuals].visual.blue_mask = 0;
167               visuals[nvisuals].visual.blue_shift = 0;
168               visuals[nvisuals].visual.blue_prec = 0;
169             }
170
171           nvisuals += 1;
172         }
173     }
174
175   if (visual_list)
176     XFree (visual_list);
177
178   for (i = 0; i < nvisuals; i++)
179     {
180       for (j = i+1; j < nvisuals; j++)
181         {
182           if (visuals[j].visual.depth >= visuals[i].visual.depth)
183             {
184               if ((visuals[j].visual.depth == 8) && (visuals[i].visual.depth == 8))
185                 {
186                   if (visuals[j].visual.type == GDK_VISUAL_PSEUDO_COLOR)
187                     {
188                       temp_visual = visuals[j];
189                       visuals[j] = visuals[i];
190                       visuals[i] = temp_visual;
191                     }
192                   else if ((visuals[i].visual.type != GDK_VISUAL_PSEUDO_COLOR) &&
193                            visuals[j].visual.type > visuals[i].visual.type)
194                     {
195                       temp_visual = visuals[j];
196                       visuals[j] = visuals[i];
197                       visuals[i] = temp_visual;
198                     }
199                 }
200               else if ((visuals[j].visual.depth > visuals[i].visual.depth) ||
201                        ((visuals[j].visual.depth == visuals[i].visual.depth) &&
202                         (visuals[j].visual.type > visuals[i].visual.type)))
203                 {
204                   temp_visual = visuals[j];
205                   visuals[j] = visuals[i];
206                   visuals[i] = temp_visual;
207                 }
208             }
209         }
210     }
211
212   for (i = 0; i < nvisuals; i++)
213     if (default_xvisual->visualid == visuals[i].xvisual->visualid)
214       {
215         system_visual = &visuals[i];
216         break;
217       }
218
219 #ifdef G_ENABLE_DEBUG 
220   if (gdk_debug_flags & GDK_DEBUG_MISC)
221     for (i = 0; i < nvisuals; i++)
222       g_message ("visual: %s: %d",
223                  visual_names[visuals[i].visual.type],
224                  visuals[i].visual.depth);
225 #endif /* G_ENABLE_DEBUG */
226
227   navailable_depths = 0;
228   for (i = 0; i < npossible_depths; i++)
229     {
230       for (j = 0; j < nvisuals; j++)
231         {
232           if (visuals[j].visual.depth == possible_depths[i])
233             {
234               available_depths[navailable_depths++] = visuals[j].visual.depth;
235               break;
236             }
237         }
238     }
239
240   if (navailable_depths == 0)
241     g_error ("unable to find a usable depth");
242
243   navailable_types = 0;
244   for (i = 0; i < npossible_types; i++)
245     {
246       for (j = 0; j < nvisuals; j++)
247         {
248           if (visuals[j].visual.type == possible_types[i])
249             {
250               available_types[navailable_types++] = visuals[j].visual.type;
251               break;
252             }
253         }
254     }
255
256   for (i = 0; i < nvisuals; i++)
257     gdk_visual_add ((GdkVisual*) &visuals[i]);
258
259   if (npossible_types == 0)
260     g_error ("unable to find a usable visual type");
261 }
262
263 GdkVisual*
264 gdk_visual_ref (GdkVisual *visual)
265 {
266   return visual;
267 }
268
269 void
270 gdk_visual_unref (GdkVisual *visual)
271 {
272   return;
273 }
274
275 gint
276 gdk_visual_get_best_depth (void)
277 {
278   return available_depths[0];
279 }
280
281 GdkVisualType
282 gdk_visual_get_best_type (void)
283 {
284   return available_types[0];
285 }
286
287 GdkVisual*
288 gdk_visual_get_system (void)
289 {
290   return ((GdkVisual*) system_visual);
291 }
292
293 GdkVisual*
294 gdk_visual_get_best (void)
295 {
296   return ((GdkVisual*) &(visuals[0]));
297 }
298
299 GdkVisual*
300 gdk_visual_get_best_with_depth (gint depth)
301 {
302   GdkVisual *return_val;
303   int i;
304
305   return_val = NULL;
306   for (i = 0; i < nvisuals; i++)
307     if (depth == visuals[i].visual.depth)
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_type (GdkVisualType visual_type)
318 {
319   GdkVisual *return_val;
320   int i;
321
322   return_val = NULL;
323   for (i = 0; i < nvisuals; i++)
324     if (visual_type == visuals[i].visual.type)
325       {
326         return_val = (GdkVisual*) &(visuals[i]);
327         break;
328       }
329
330   return return_val;
331 }
332
333 GdkVisual*
334 gdk_visual_get_best_with_both (gint          depth,
335                                GdkVisualType visual_type)
336 {
337   GdkVisual *return_val;
338   int i;
339
340   return_val = NULL;
341   for (i = 0; i < nvisuals; i++)
342     if ((depth == visuals[i].visual.depth) &&
343         (visual_type == visuals[i].visual.type))
344       {
345         return_val = (GdkVisual*) &(visuals[i]);
346         break;
347       }
348
349   return return_val;
350 }
351
352 void
353 gdk_query_depths  (gint **depths,
354                    gint  *count)
355 {
356   *count = navailable_depths;
357   *depths = available_depths;
358 }
359
360 void
361 gdk_query_visual_types (GdkVisualType **visual_types,
362                         gint           *count)
363 {
364   *count = navailable_types;
365   *visual_types = available_types;
366 }
367
368 GList*
369 gdk_list_visuals (void)
370 {
371   GList *list;
372   guint i;
373
374   list = NULL;
375   for (i = 0; i < nvisuals; ++i)
376     list = g_list_append (list, (gpointer) &visuals[i]);
377
378   return list;
379 }
380
381
382 GdkVisual*
383 gdk_visual_lookup (Visual *xvisual)
384 {
385   GdkVisual *visual;
386
387   if (!visual_hash)
388     return NULL;
389
390   visual = g_hash_table_lookup (visual_hash, xvisual);
391   return visual;
392 }
393
394 GdkVisual*
395 gdkx_visual_get (VisualID xvisualid)
396 {
397   int i;
398
399   for (i = 0; i < nvisuals; i++)
400     if (xvisualid == visuals[i].xvisual->visualid)
401       return (GdkVisual*) &visuals[i];
402
403   return NULL;
404 }
405
406
407 static void
408 gdk_visual_add (GdkVisual *visual)
409 {
410   GdkVisualPrivate *private;
411
412   if (!visual_hash)
413     visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
414                                     (GCompareFunc) gdk_visual_compare);
415
416   private = (GdkVisualPrivate*) visual;
417
418   g_hash_table_insert (visual_hash, private->xvisual, visual);
419 }
420
421 static void
422 gdk_visual_decompose_mask (gulong  mask,
423                            gint   *shift,
424                            gint   *prec)
425 {
426   *shift = 0;
427   *prec = 0;
428
429   while (!(mask & 0x1))
430     {
431       (*shift)++;
432       mask >>= 1;
433     }
434
435   while (mask & 0x1)
436     {
437       (*prec)++;
438       mask >>= 1;
439     }
440 }
441
442 static guint
443 gdk_visual_hash (Visual *key)
444 {
445   return key->visualid;
446 }
447
448 static gint
449 gdk_visual_compare (Visual *a,
450                     Visual *b)
451 {
452   return (a->visualid == b->visualid);
453 }