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