]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkvisual-x11.c
GdkFrameClockIdle: don't start the tiemout/idle when in a frame
[~andy/gtk] / gdk / x11 / gdkvisual-x11.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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 /*
19  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20  * file for a list of people on the GTK+ Team.  See the ChangeLog
21  * files for a list of changes.  These files are distributed with
22  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
23  */
24
25 #include "config.h"
26
27 #include "gdkvisualprivate.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkscreen-x11.h"
30
31 #include <X11/Xlib.h>
32 #include <X11/Xutil.h>
33
34 struct _GdkX11Visual
35 {
36   GdkVisual visual;
37
38   Visual *xvisual;
39   Colormap colormap;
40 };
41
42 struct _GdkX11VisualClass
43 {
44   GdkVisualClass visual_class;
45 };
46
47 static void     gdk_visual_add            (GdkVisual *visual);
48 static void     gdk_visual_decompose_mask (gulong     mask,
49                                            gint      *shift,
50                                            gint      *prec);
51 static guint    gdk_visual_hash           (Visual    *key);
52 static gboolean gdk_visual_equal          (Visual    *a,
53                                            Visual    *b);
54
55
56 #ifdef G_ENABLE_DEBUG
57
58 static const gchar *const visual_names[] =
59 {
60   "static gray",
61   "grayscale",
62   "static color",
63   "pseudo color",
64   "true color",
65   "direct color",
66 };
67
68 #endif /* G_ENABLE_DEBUG */
69
70 G_DEFINE_TYPE (GdkX11Visual, gdk_x11_visual, GDK_TYPE_VISUAL)
71
72 static void
73 gdk_x11_visual_init (GdkX11Visual *x11_visual)
74 {
75   x11_visual->colormap = None;
76 }
77
78 static void
79 gdk_x11_visual_finalize (GObject *object)
80 {
81   GdkVisual *visual = (GdkVisual *)object;
82   GdkX11Visual *x11_visual = (GdkX11Visual *)object;
83
84   if (x11_visual->colormap != None)
85     XFreeColormap (GDK_SCREEN_XDISPLAY (visual->screen), x11_visual->colormap);
86
87   G_OBJECT_CLASS (gdk_x11_visual_parent_class)->finalize (object);
88 }
89
90 static void
91 gdk_x11_visual_class_init (GdkX11VisualClass *class)
92 {
93   GObjectClass *object_class = G_OBJECT_CLASS (class);
94
95   object_class->finalize = gdk_x11_visual_finalize;
96 }
97
98 void
99 _gdk_x11_screen_init_visuals (GdkScreen *screen)
100 {
101   static const gint possible_depths[8] = { 32, 30, 24, 16, 15, 8, 4, 1 };
102   static const GdkVisualType possible_types[6] =
103     {
104       GDK_VISUAL_DIRECT_COLOR,
105       GDK_VISUAL_TRUE_COLOR,
106       GDK_VISUAL_PSEUDO_COLOR,
107       GDK_VISUAL_STATIC_COLOR,
108       GDK_VISUAL_GRAYSCALE,
109       GDK_VISUAL_STATIC_GRAY
110     };
111
112   GdkX11Screen *x11_screen;
113   XVisualInfo *visual_list;
114   XVisualInfo visual_template;
115   GdkVisual *temp_visual;
116   Visual *default_xvisual;
117   GdkVisual **visuals;
118   int nxvisuals;
119   int nvisuals;
120   int i, j;
121
122   g_return_if_fail (GDK_IS_SCREEN (screen));
123   x11_screen = GDK_X11_SCREEN (screen);
124
125   nxvisuals = 0;
126   visual_template.screen = x11_screen->screen_num;
127   visual_list = XGetVisualInfo (x11_screen->xdisplay, VisualScreenMask, &visual_template, &nxvisuals);
128
129   visuals = g_new (GdkVisual *, nxvisuals);
130   for (i = 0; i < nxvisuals; i++)
131     visuals[i] = g_object_new (GDK_TYPE_X11_VISUAL, NULL);
132
133   default_xvisual = DefaultVisual (x11_screen->xdisplay, x11_screen->screen_num);
134
135   nvisuals = 0;
136   for (i = 0; i < nxvisuals; i++)
137     {
138       visuals[nvisuals]->screen = screen;
139
140       if (visual_list[i].depth >= 1)
141         {
142 #ifdef __cplusplus
143           switch (visual_list[i].c_class)
144 #else /* __cplusplus */
145           switch (visual_list[i].class)
146 #endif /* __cplusplus */
147             {
148             case StaticGray:
149               visuals[nvisuals]->type = GDK_VISUAL_STATIC_GRAY;
150               break;
151             case GrayScale:
152               visuals[nvisuals]->type = GDK_VISUAL_GRAYSCALE;
153               break;
154             case StaticColor:
155               visuals[nvisuals]->type = GDK_VISUAL_STATIC_COLOR;
156               break;
157             case PseudoColor:
158               visuals[nvisuals]->type = GDK_VISUAL_PSEUDO_COLOR;
159               break;
160             case TrueColor:
161               visuals[nvisuals]->type = GDK_VISUAL_TRUE_COLOR;
162               break;
163             case DirectColor:
164               visuals[nvisuals]->type = GDK_VISUAL_DIRECT_COLOR;
165               break;
166             }
167
168           visuals[nvisuals]->depth = visual_list[i].depth;
169           visuals[nvisuals]->byte_order =
170             (ImageByteOrder(x11_screen->xdisplay) == LSBFirst) ?
171             GDK_LSB_FIRST : GDK_MSB_FIRST;
172           visuals[nvisuals]->red_mask = visual_list[i].red_mask;
173           visuals[nvisuals]->green_mask = visual_list[i].green_mask;
174           visuals[nvisuals]->blue_mask = visual_list[i].blue_mask;
175           visuals[nvisuals]->colormap_size = visual_list[i].colormap_size;
176           visuals[nvisuals]->bits_per_rgb = visual_list[i].bits_per_rgb;
177           GDK_X11_VISUAL (visuals[nvisuals])->xvisual = visual_list[i].visual;
178
179           if ((visuals[nvisuals]->type == GDK_VISUAL_TRUE_COLOR) ||
180               (visuals[nvisuals]->type == GDK_VISUAL_DIRECT_COLOR))
181             {
182               gdk_visual_decompose_mask (visuals[nvisuals]->red_mask,
183                                          &visuals[nvisuals]->red_shift,
184                                          &visuals[nvisuals]->red_prec);
185
186               gdk_visual_decompose_mask (visuals[nvisuals]->green_mask,
187                                          &visuals[nvisuals]->green_shift,
188                                          &visuals[nvisuals]->green_prec);
189
190               gdk_visual_decompose_mask (visuals[nvisuals]->blue_mask,
191                                          &visuals[nvisuals]->blue_shift,
192                                          &visuals[nvisuals]->blue_prec);
193             }
194           else
195             {
196               visuals[nvisuals]->red_mask = 0;
197               visuals[nvisuals]->red_shift = 0;
198               visuals[nvisuals]->red_prec = 0;
199
200               visuals[nvisuals]->green_mask = 0;
201               visuals[nvisuals]->green_shift = 0;
202               visuals[nvisuals]->green_prec = 0;
203
204               visuals[nvisuals]->blue_mask = 0;
205               visuals[nvisuals]->blue_shift = 0;
206               visuals[nvisuals]->blue_prec = 0;
207             }
208
209           nvisuals += 1;
210         }
211     }
212
213   if (visual_list)
214     XFree (visual_list);
215
216   for (i = 0; i < nvisuals; i++)
217     {
218       for (j = i+1; j < nvisuals; j++)
219         {
220           if (visuals[j]->depth >= visuals[i]->depth)
221             {
222               if ((visuals[j]->depth == 8) && (visuals[i]->depth == 8))
223                 {
224                   if (visuals[j]->type == GDK_VISUAL_PSEUDO_COLOR)
225                     {
226                       temp_visual = visuals[j];
227                       visuals[j] = visuals[i];
228                       visuals[i] = temp_visual;
229                     }
230                   else if ((visuals[i]->type != GDK_VISUAL_PSEUDO_COLOR) &&
231                            visuals[j]->type > visuals[i]->type)
232                     {
233                       temp_visual = visuals[j];
234                       visuals[j] = visuals[i];
235                       visuals[i] = temp_visual;
236                     }
237                 }
238               else if ((visuals[j]->depth > visuals[i]->depth) ||
239                        ((visuals[j]->depth == visuals[i]->depth) &&
240                         (visuals[j]->type > visuals[i]->type)))
241                 {
242                   temp_visual = visuals[j];
243                   visuals[j] = visuals[i];
244                   visuals[i] = temp_visual;
245                 }
246             }
247         }
248     }
249
250   for (i = 0; i < nvisuals; i++)
251     {
252       if (default_xvisual->visualid == GDK_X11_VISUAL (visuals[i])->xvisual->visualid)
253          {
254            x11_screen->system_visual = visuals[i];
255            GDK_X11_VISUAL (visuals[i])->colormap =
256                DefaultColormap (x11_screen->xdisplay, x11_screen->screen_num);
257          }
258
259       /* For now, we only support 8888 ARGB for the "rgba visual".
260        * Additional formats (like ABGR) could be added later if they
261        * turn up.
262        */
263       if (visuals[i]->depth == 32 &&
264           (visuals[i]->red_mask   == 0xff0000 &&
265            visuals[i]->green_mask == 0x00ff00 &&
266            visuals[i]->blue_mask  == 0x0000ff))
267         {
268           x11_screen->rgba_visual = visuals[i];
269         }
270     }
271
272 #ifdef G_ENABLE_DEBUG
273   if (_gdk_debug_flags & GDK_DEBUG_MISC)
274     {
275       static const gchar *const visual_names[] =
276       {
277         "static gray",
278         "grayscale",
279         "static color",
280         "pseudo color",
281         "true color",
282         "direct color",
283       };
284
285       for (i = 0; i < nvisuals; i++)
286         g_message ("visual: %s: %d", visual_names[visuals[i]->type], visuals[i]->depth);
287     }
288 #endif /* G_ENABLE_DEBUG */
289
290   x11_screen->navailable_depths = 0;
291   for (i = 0; i < G_N_ELEMENTS (possible_depths); i++)
292     {
293       for (j = 0; j < nvisuals; j++)
294         {
295           if (visuals[j]->depth == possible_depths[i])
296             {
297               x11_screen->available_depths[x11_screen->navailable_depths++] = visuals[j]->depth;
298               break;
299             }
300         }
301     }
302
303   if (x11_screen->navailable_depths == 0)
304     g_error ("unable to find a usable depth");
305
306   x11_screen->navailable_types = 0;
307   for (i = 0; i < G_N_ELEMENTS (possible_types); i++)
308     {
309       for (j = 0; j < nvisuals; j++)
310         {
311           if (visuals[j]->type == possible_types[i])
312             {
313               x11_screen->available_types[x11_screen->navailable_types++] = visuals[j]->type;
314               break;
315             }
316         }
317     }
318
319   for (i = 0; i < nvisuals; i++)
320     gdk_visual_add (visuals[i]);
321
322   if (x11_screen->navailable_types == 0)
323     g_error ("unable to find a usable visual type");
324
325   x11_screen->visuals = visuals;
326   x11_screen->nvisuals = nvisuals;
327 }
328
329 gint
330 _gdk_x11_screen_visual_get_best_depth (GdkScreen *screen)
331 {
332   return GDK_X11_SCREEN (screen)->available_depths[0];
333 }
334
335 GdkVisualType
336 _gdk_x11_screen_visual_get_best_type (GdkScreen *screen)
337 {
338   return GDK_X11_SCREEN (screen)->available_types[0];
339 }
340
341 GdkVisual *
342 _gdk_x11_screen_get_system_visual (GdkScreen *screen)
343 {
344   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
345
346   return ((GdkVisual *) GDK_X11_SCREEN (screen)->system_visual);
347 }
348
349 GdkVisual*
350 _gdk_x11_screen_visual_get_best (GdkScreen *screen)
351 {
352   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
353
354   return x11_screen->visuals[0];
355 }
356
357 GdkVisual*
358 _gdk_x11_screen_visual_get_best_with_depth (GdkScreen *screen,
359                                             gint       depth)
360 {
361   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
362   GdkVisual *return_val;
363   int i;
364   
365   return_val = NULL;
366   for (i = 0; i < x11_screen->nvisuals; i++)
367     if (depth == x11_screen->visuals[i]->depth)
368       {
369         return_val = x11_screen->visuals[i];
370         break;
371       }
372
373   return return_val;
374 }
375
376 GdkVisual*
377 _gdk_x11_screen_visual_get_best_with_type (GdkScreen     *screen,
378                                            GdkVisualType  visual_type)
379 {
380   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
381   GdkVisual *return_val;
382   int i;
383
384   return_val = NULL;
385   for (i = 0; i < x11_screen->nvisuals; i++)
386     if (visual_type == x11_screen->visuals[i]->type)
387       {
388         return_val = x11_screen->visuals[i];
389         break;
390       }
391
392   return return_val;
393 }
394
395 GdkVisual*
396 _gdk_x11_screen_visual_get_best_with_both (GdkScreen     *screen,
397                                            gint           depth,
398                                            GdkVisualType  visual_type)
399 {
400   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
401   GdkVisual *return_val;
402   int i;
403
404   return_val = NULL;
405   for (i = 0; i < x11_screen->nvisuals; i++)
406     if ((depth == x11_screen->visuals[i]->depth) &&
407         (visual_type == x11_screen->visuals[i]->type))
408       {
409         return_val = x11_screen->visuals[i];
410         break;
411       }
412
413   return return_val;
414 }
415
416 void
417 _gdk_x11_screen_query_depths  (GdkScreen  *screen,
418                                gint      **depths,
419                                gint       *count)
420 {
421   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
422
423   *count = x11_screen->navailable_depths;
424   *depths = x11_screen->available_depths;
425 }
426
427 void
428 _gdk_x11_screen_query_visual_types (GdkScreen      *screen,
429                                     GdkVisualType **visual_types,
430                                     gint           *count)
431 {
432   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
433
434   *count = x11_screen->navailable_types;
435   *visual_types = x11_screen->available_types;
436 }
437
438 GList *
439 _gdk_x11_screen_list_visuals (GdkScreen *screen)
440 {
441   GList *list;
442   GdkX11Screen *x11_screen;
443   guint i;
444
445   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
446   x11_screen = GDK_X11_SCREEN (screen);
447
448   list = NULL;
449
450   for (i = 0; i < x11_screen->nvisuals; ++i)
451     list = g_list_append (list, x11_screen->visuals[i]);
452
453   return list;
454 }
455
456 /**
457  * gdk_x11_screen_lookup_visual:
458  * @screen: (type GdkX11Screen): a #GdkScreen.
459  * @xvisualid: an X Visual ID.
460  *
461  * Looks up the #GdkVisual for a particular screen and X Visual ID.
462  *
463  * Returns: (transfer none): the #GdkVisual (owned by the screen
464  *   object), or %NULL if the visual ID wasn't found.
465  *
466  * Since: 2.2
467  */
468 GdkVisual *
469 gdk_x11_screen_lookup_visual (GdkScreen *screen,
470                               VisualID   xvisualid)
471 {
472   int i;
473   GdkX11Screen *x11_screen;
474   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
475   x11_screen = GDK_X11_SCREEN (screen);
476
477   for (i = 0; i < x11_screen->nvisuals; i++)
478     if (xvisualid == GDK_X11_VISUAL (x11_screen->visuals[i])->xvisual->visualid)
479       return x11_screen->visuals[i];
480
481   return NULL;
482 }
483
484 static void
485 gdk_visual_add (GdkVisual *visual)
486 {
487   GdkX11Screen *x11_screen = GDK_X11_SCREEN (visual->screen);
488
489   if (!x11_screen->visual_hash)
490     x11_screen->visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
491                                                 (GEqualFunc) gdk_visual_equal);
492
493   g_hash_table_insert (x11_screen->visual_hash, GDK_X11_VISUAL (visual)->xvisual, visual);
494 }
495
496 static void
497 gdk_visual_decompose_mask (gulong  mask,
498                            gint   *shift,
499                            gint   *prec)
500 {
501   *shift = 0;
502   *prec = 0;
503
504   if (mask == 0)
505     {
506       g_warning ("Mask is 0 in visual. Server bug ?");
507       return;
508     }
509
510   while (!(mask & 0x1))
511     {
512       (*shift)++;
513       mask >>= 1;
514     }
515
516   while (mask & 0x1)
517     {
518       (*prec)++;
519       mask >>= 1;
520     }
521 }
522
523 static guint
524 gdk_visual_hash (Visual *key)
525 {
526   return key->visualid;
527 }
528
529 static gboolean
530 gdk_visual_equal (Visual *a,
531                   Visual *b)
532 {
533   return (a->visualid == b->visualid);
534 }
535
536 /**
537  * _gdk_visual_get_x11_colormap:
538  * @visual: the visual to get the colormap from
539  *
540  * Gets the colormap to use
541  *
542  * Returns: the X Colormap to use for new windows using @visual
543  **/
544 Colormap
545 _gdk_visual_get_x11_colormap (GdkVisual *visual)
546 {
547   GdkX11Visual *x11_visual;
548
549   g_return_val_if_fail (GDK_IS_VISUAL (visual), None);
550
551   x11_visual = GDK_X11_VISUAL (visual);
552
553   if (x11_visual->colormap == None)
554     {
555       x11_visual->colormap = XCreateColormap (GDK_SCREEN_XDISPLAY (visual->screen),
556                                               GDK_SCREEN_XROOTWIN (visual->screen),
557                                               x11_visual->xvisual,
558                                               AllocNone);
559     }
560
561   return x11_visual->colormap;
562 }
563
564 /**
565  * gdk_x11_visual_get_xvisual:
566  * @visual: a #GdkVisual.
567  *
568  * Returns the X visual belonging to a #GdkVisual.
569  *
570  * Return value: (transfer none): an Xlib <type>Visual*</type>.
571  **/
572 Visual *
573 gdk_x11_visual_get_xvisual (GdkVisual *visual)
574 {
575   g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
576
577   return GDK_X11_VISUAL (visual)->xvisual;
578 }