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