1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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/>.
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/.
27 #include "gdkvisualprivate.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkscreen-x11.h"
32 #include <X11/Xutil.h>
42 struct _GdkX11VisualClass
44 GdkVisualClass visual_class;
47 static void gdk_visual_add (GdkVisual *visual);
48 static void gdk_visual_decompose_mask (gulong mask,
51 static guint gdk_visual_hash (Visual *key);
52 static gboolean gdk_visual_equal (Visual *a,
58 static const gchar *const visual_names[] =
68 #endif /* G_ENABLE_DEBUG */
70 G_DEFINE_TYPE (GdkX11Visual, gdk_x11_visual, GDK_TYPE_VISUAL)
73 gdk_x11_visual_init (GdkX11Visual *x11_visual)
75 x11_visual->colormap = None;
79 gdk_x11_visual_finalize (GObject *object)
81 GdkVisual *visual = (GdkVisual *)object;
82 GdkX11Visual *x11_visual = (GdkX11Visual *)object;
84 if (x11_visual->colormap != None)
85 XFreeColormap (GDK_SCREEN_XDISPLAY (visual->screen), x11_visual->colormap);
87 G_OBJECT_CLASS (gdk_x11_visual_parent_class)->finalize (object);
91 gdk_x11_visual_class_init (GdkX11VisualClass *class)
93 GObjectClass *object_class = G_OBJECT_CLASS (class);
95 object_class->finalize = gdk_x11_visual_finalize;
99 _gdk_x11_screen_init_visuals (GdkScreen *screen)
101 static const gint possible_depths[8] = { 32, 30, 24, 16, 15, 8, 4, 1 };
102 static const GdkVisualType possible_types[6] =
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
112 GdkX11Screen *x11_screen;
113 XVisualInfo *visual_list;
114 XVisualInfo visual_template;
115 GdkVisual *temp_visual;
116 Visual *default_xvisual;
122 g_return_if_fail (GDK_IS_SCREEN (screen));
123 x11_screen = GDK_X11_SCREEN (screen);
126 visual_template.screen = x11_screen->screen_num;
127 visual_list = XGetVisualInfo (x11_screen->xdisplay, VisualScreenMask, &visual_template, &nxvisuals);
129 visuals = g_new (GdkVisual *, nxvisuals);
130 for (i = 0; i < nxvisuals; i++)
131 visuals[i] = g_object_new (GDK_TYPE_X11_VISUAL, NULL);
133 default_xvisual = DefaultVisual (x11_screen->xdisplay, x11_screen->screen_num);
136 for (i = 0; i < nxvisuals; i++)
138 visuals[nvisuals]->screen = screen;
140 if (visual_list[i].depth >= 1)
143 switch (visual_list[i].c_class)
144 #else /* __cplusplus */
145 switch (visual_list[i].class)
146 #endif /* __cplusplus */
149 visuals[nvisuals]->type = GDK_VISUAL_STATIC_GRAY;
152 visuals[nvisuals]->type = GDK_VISUAL_GRAYSCALE;
155 visuals[nvisuals]->type = GDK_VISUAL_STATIC_COLOR;
158 visuals[nvisuals]->type = GDK_VISUAL_PSEUDO_COLOR;
161 visuals[nvisuals]->type = GDK_VISUAL_TRUE_COLOR;
164 visuals[nvisuals]->type = GDK_VISUAL_DIRECT_COLOR;
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;
179 if ((visuals[nvisuals]->type == GDK_VISUAL_TRUE_COLOR) ||
180 (visuals[nvisuals]->type == GDK_VISUAL_DIRECT_COLOR))
182 gdk_visual_decompose_mask (visuals[nvisuals]->red_mask,
183 &visuals[nvisuals]->red_shift,
184 &visuals[nvisuals]->red_prec);
186 gdk_visual_decompose_mask (visuals[nvisuals]->green_mask,
187 &visuals[nvisuals]->green_shift,
188 &visuals[nvisuals]->green_prec);
190 gdk_visual_decompose_mask (visuals[nvisuals]->blue_mask,
191 &visuals[nvisuals]->blue_shift,
192 &visuals[nvisuals]->blue_prec);
196 visuals[nvisuals]->red_mask = 0;
197 visuals[nvisuals]->red_shift = 0;
198 visuals[nvisuals]->red_prec = 0;
200 visuals[nvisuals]->green_mask = 0;
201 visuals[nvisuals]->green_shift = 0;
202 visuals[nvisuals]->green_prec = 0;
204 visuals[nvisuals]->blue_mask = 0;
205 visuals[nvisuals]->blue_shift = 0;
206 visuals[nvisuals]->blue_prec = 0;
216 for (i = 0; i < nvisuals; i++)
218 for (j = i+1; j < nvisuals; j++)
220 if (visuals[j]->depth >= visuals[i]->depth)
222 if ((visuals[j]->depth == 8) && (visuals[i]->depth == 8))
224 if (visuals[j]->type == GDK_VISUAL_PSEUDO_COLOR)
226 temp_visual = visuals[j];
227 visuals[j] = visuals[i];
228 visuals[i] = temp_visual;
230 else if ((visuals[i]->type != GDK_VISUAL_PSEUDO_COLOR) &&
231 visuals[j]->type > visuals[i]->type)
233 temp_visual = visuals[j];
234 visuals[j] = visuals[i];
235 visuals[i] = temp_visual;
238 else if ((visuals[j]->depth > visuals[i]->depth) ||
239 ((visuals[j]->depth == visuals[i]->depth) &&
240 (visuals[j]->type > visuals[i]->type)))
242 temp_visual = visuals[j];
243 visuals[j] = visuals[i];
244 visuals[i] = temp_visual;
250 for (i = 0; i < nvisuals; i++)
252 if (default_xvisual->visualid == GDK_X11_VISUAL (visuals[i])->xvisual->visualid)
254 x11_screen->system_visual = visuals[i];
255 GDK_X11_VISUAL (visuals[i])->colormap =
256 DefaultColormap (x11_screen->xdisplay, x11_screen->screen_num);
259 /* For now, we only support 8888 ARGB for the "rgba visual".
260 * Additional formats (like ABGR) could be added later if they
263 if (visuals[i]->depth == 32 &&
264 (visuals[i]->red_mask == 0xff0000 &&
265 visuals[i]->green_mask == 0x00ff00 &&
266 visuals[i]->blue_mask == 0x0000ff))
268 x11_screen->rgba_visual = visuals[i];
272 #ifdef G_ENABLE_DEBUG
273 if (_gdk_debug_flags & GDK_DEBUG_MISC)
275 static const gchar *const visual_names[] =
285 for (i = 0; i < nvisuals; i++)
286 g_message ("visual: %s: %d", visual_names[visuals[i]->type], visuals[i]->depth);
288 #endif /* G_ENABLE_DEBUG */
290 x11_screen->navailable_depths = 0;
291 for (i = 0; i < G_N_ELEMENTS (possible_depths); i++)
293 for (j = 0; j < nvisuals; j++)
295 if (visuals[j]->depth == possible_depths[i])
297 x11_screen->available_depths[x11_screen->navailable_depths++] = visuals[j]->depth;
303 if (x11_screen->navailable_depths == 0)
304 g_error ("unable to find a usable depth");
306 x11_screen->navailable_types = 0;
307 for (i = 0; i < G_N_ELEMENTS (possible_types); i++)
309 for (j = 0; j < nvisuals; j++)
311 if (visuals[j]->type == possible_types[i])
313 x11_screen->available_types[x11_screen->navailable_types++] = visuals[j]->type;
319 for (i = 0; i < nvisuals; i++)
320 gdk_visual_add (visuals[i]);
322 if (x11_screen->navailable_types == 0)
323 g_error ("unable to find a usable visual type");
325 x11_screen->visuals = visuals;
326 x11_screen->nvisuals = nvisuals;
330 _gdk_x11_screen_visual_get_best_depth (GdkScreen *screen)
332 return GDK_X11_SCREEN (screen)->available_depths[0];
336 _gdk_x11_screen_visual_get_best_type (GdkScreen *screen)
338 return GDK_X11_SCREEN (screen)->available_types[0];
342 _gdk_x11_screen_get_system_visual (GdkScreen *screen)
344 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
346 return ((GdkVisual *) GDK_X11_SCREEN (screen)->system_visual);
350 _gdk_x11_screen_visual_get_best (GdkScreen *screen)
352 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
354 return x11_screen->visuals[0];
358 _gdk_x11_screen_visual_get_best_with_depth (GdkScreen *screen,
361 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
362 GdkVisual *return_val;
366 for (i = 0; i < x11_screen->nvisuals; i++)
367 if (depth == x11_screen->visuals[i]->depth)
369 return_val = x11_screen->visuals[i];
377 _gdk_x11_screen_visual_get_best_with_type (GdkScreen *screen,
378 GdkVisualType visual_type)
380 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
381 GdkVisual *return_val;
385 for (i = 0; i < x11_screen->nvisuals; i++)
386 if (visual_type == x11_screen->visuals[i]->type)
388 return_val = x11_screen->visuals[i];
396 _gdk_x11_screen_visual_get_best_with_both (GdkScreen *screen,
398 GdkVisualType visual_type)
400 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
401 GdkVisual *return_val;
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))
409 return_val = x11_screen->visuals[i];
417 _gdk_x11_screen_query_depths (GdkScreen *screen,
421 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
423 *count = x11_screen->navailable_depths;
424 *depths = x11_screen->available_depths;
428 _gdk_x11_screen_query_visual_types (GdkScreen *screen,
429 GdkVisualType **visual_types,
432 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
434 *count = x11_screen->navailable_types;
435 *visual_types = x11_screen->available_types;
439 _gdk_x11_screen_list_visuals (GdkScreen *screen)
442 GdkX11Screen *x11_screen;
445 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
446 x11_screen = GDK_X11_SCREEN (screen);
450 for (i = 0; i < x11_screen->nvisuals; ++i)
451 list = g_list_append (list, x11_screen->visuals[i]);
457 * gdk_x11_screen_lookup_visual:
458 * @screen: (type GdkX11Screen): a #GdkScreen.
459 * @xvisualid: an X Visual ID.
461 * Looks up the #GdkVisual for a particular screen and X Visual ID.
463 * Returns: (transfer none): the #GdkVisual (owned by the screen
464 * object), or %NULL if the visual ID wasn't found.
469 gdk_x11_screen_lookup_visual (GdkScreen *screen,
473 GdkX11Screen *x11_screen;
474 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
475 x11_screen = GDK_X11_SCREEN (screen);
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];
485 gdk_visual_add (GdkVisual *visual)
487 GdkX11Screen *x11_screen = GDK_X11_SCREEN (visual->screen);
489 if (!x11_screen->visual_hash)
490 x11_screen->visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
491 (GEqualFunc) gdk_visual_equal);
493 g_hash_table_insert (x11_screen->visual_hash, GDK_X11_VISUAL (visual)->xvisual, visual);
497 gdk_visual_decompose_mask (gulong mask,
506 g_warning ("Mask is 0 in visual. Server bug ?");
510 while (!(mask & 0x1))
524 gdk_visual_hash (Visual *key)
526 return key->visualid;
530 gdk_visual_equal (Visual *a,
533 return (a->visualid == b->visualid);
537 * _gdk_visual_get_x11_colormap:
538 * @visual: the visual to get the colormap from
540 * Gets the colormap to use
542 * Returns: the X Colormap to use for new windows using @visual
545 _gdk_visual_get_x11_colormap (GdkVisual *visual)
547 GdkX11Visual *x11_visual;
549 g_return_val_if_fail (GDK_IS_VISUAL (visual), None);
551 x11_visual = GDK_X11_VISUAL (visual);
553 if (x11_visual->colormap == None)
555 x11_visual->colormap = XCreateColormap (GDK_SCREEN_XDISPLAY (visual->screen),
556 GDK_SCREEN_XROOTWIN (visual->screen),
561 return x11_visual->colormap;
565 * gdk_x11_visual_get_xvisual:
566 * @visual: a #GdkVisual.
568 * Returns the X visual belonging to a #GdkVisual.
570 * Return value: (transfer none): an Xlib <type>Visual*</type>.
573 gdk_x11_visual_get_xvisual (GdkVisual *visual)
575 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
577 return GDK_X11_VISUAL (visual)->xvisual;