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 guint gdk_visual_hash (Visual *key);
49 static gboolean gdk_visual_equal (Visual *a,
50 Visual *b);
51
52
G_DEFINE_TYPE(GdkX11Visual,gdk_x11_visual,GDK_TYPE_VISUAL)53 G_DEFINE_TYPE (GdkX11Visual, gdk_x11_visual, GDK_TYPE_VISUAL)
54
55 static void
56 gdk_x11_visual_init (GdkX11Visual *x11_visual)
57 {
58 x11_visual->colormap = None;
59 }
60
61 static void
gdk_x11_visual_finalize(GObject * object)62 gdk_x11_visual_finalize (GObject *object)
63 {
64 GdkVisual *visual = (GdkVisual *)object;
65 GdkX11Visual *x11_visual = (GdkX11Visual *)object;
66
67 if (x11_visual->colormap != None)
68 XFreeColormap (GDK_SCREEN_XDISPLAY (visual->screen), x11_visual->colormap);
69
70 G_OBJECT_CLASS (gdk_x11_visual_parent_class)->finalize (object);
71 }
72
73 static void
gdk_x11_visual_dispose(GObject * object)74 gdk_x11_visual_dispose (GObject *object)
75 {
76 GdkVisual *visual = (GdkVisual *)object;
77 GdkX11Visual *x11_visual = (GdkX11Visual *)object;
78
79 if (x11_visual->colormap != None)
80 {
81 XFreeColormap (GDK_SCREEN_XDISPLAY (visual->screen), x11_visual->colormap);
82 x11_visual->colormap = None;
83 }
84
85 G_OBJECT_CLASS (gdk_x11_visual_parent_class)->dispose (object);
86 }
87
88 static void
gdk_x11_visual_class_init(GdkX11VisualClass * class)89 gdk_x11_visual_class_init (GdkX11VisualClass *class)
90 {
91 GObjectClass *object_class = G_OBJECT_CLASS (class);
92
93 object_class->finalize = gdk_x11_visual_finalize;
94 object_class->dispose = gdk_x11_visual_dispose;
95 }
96
97 void
_gdk_x11_screen_init_visuals(GdkScreen * screen)98 _gdk_x11_screen_init_visuals (GdkScreen *screen)
99 {
100 static const gint possible_depths[8] = { 32, 30, 24, 16, 15, 8, 4, 1 };
101 static const GdkVisualType possible_types[6] =
102 {
103 GDK_VISUAL_DIRECT_COLOR,
104 GDK_VISUAL_TRUE_COLOR,
105 GDK_VISUAL_PSEUDO_COLOR,
106 GDK_VISUAL_STATIC_COLOR,
107 GDK_VISUAL_GRAYSCALE,
108 GDK_VISUAL_STATIC_GRAY
109 };
110
111 GdkX11Screen *x11_screen;
112 XVisualInfo *visual_list;
113 XVisualInfo visual_template;
114 GdkVisual *temp_visual;
115 Visual *default_xvisual;
116 GdkVisual **visuals;
117 int nxvisuals;
118 int nvisuals;
119 int i, j;
120
121 g_return_if_fail (GDK_IS_SCREEN (screen));
122 x11_screen = GDK_X11_SCREEN (screen);
123
124 nxvisuals = 0;
125 visual_template.screen = x11_screen->screen_num;
126 visual_list = XGetVisualInfo (x11_screen->xdisplay, VisualScreenMask, &visual_template, &nxvisuals);
127
128 visuals = g_new (GdkVisual *, nxvisuals);
129 for (i = 0; i < nxvisuals; i++)
130 visuals[i] = g_object_new (GDK_TYPE_X11_VISUAL, NULL);
131
132 default_xvisual = DefaultVisual (x11_screen->xdisplay, x11_screen->screen_num);
133
134 nvisuals = 0;
135 for (i = 0; i < nxvisuals; i++)
136 {
137 visuals[nvisuals]->screen = screen;
138
139 if (visual_list[i].depth >= 1)
140 {
141 #ifdef __cplusplus
142 switch (visual_list[i].c_class)
143 #else /* __cplusplus */
144 switch (visual_list[i].class)
145 #endif /* __cplusplus */
146 {
147 case StaticGray:
148 visuals[nvisuals]->type = GDK_VISUAL_STATIC_GRAY;
149 break;
150 case GrayScale:
151 visuals[nvisuals]->type = GDK_VISUAL_GRAYSCALE;
152 break;
153 case StaticColor:
154 visuals[nvisuals]->type = GDK_VISUAL_STATIC_COLOR;
155 break;
156 case PseudoColor:
157 visuals[nvisuals]->type = GDK_VISUAL_PSEUDO_COLOR;
158 break;
159 case TrueColor:
160 visuals[nvisuals]->type = GDK_VISUAL_TRUE_COLOR;
161 break;
162 case DirectColor:
163 visuals[nvisuals]->type = GDK_VISUAL_DIRECT_COLOR;
164 break;
165 }
166
167 visuals[nvisuals]->depth = visual_list[i].depth;
168 visuals[nvisuals]->byte_order =
169 (ImageByteOrder(x11_screen->xdisplay) == LSBFirst) ?
170 GDK_LSB_FIRST : GDK_MSB_FIRST;
171 visuals[nvisuals]->red_mask = visual_list[i].red_mask;
172 visuals[nvisuals]->green_mask = visual_list[i].green_mask;
173 visuals[nvisuals]->blue_mask = visual_list[i].blue_mask;
174 visuals[nvisuals]->colormap_size = visual_list[i].colormap_size;
175 visuals[nvisuals]->bits_per_rgb = visual_list[i].bits_per_rgb;
176 GDK_X11_VISUAL (visuals[nvisuals])->xvisual = visual_list[i].visual;
177
178 if ((visuals[nvisuals]->type != GDK_VISUAL_TRUE_COLOR) &&
179 (visuals[nvisuals]->type != GDK_VISUAL_DIRECT_COLOR))
180 {
181 visuals[nvisuals]->red_mask = 0;
182 visuals[nvisuals]->green_mask = 0;
183 visuals[nvisuals]->blue_mask = 0;
184 }
185
186 nvisuals += 1;
187 }
188 }
189
190 if (visual_list)
191 XFree (visual_list);
192
193 for (i = 0; i < nvisuals; i++)
194 {
195 for (j = i+1; j < nvisuals; j++)
196 {
197 if (visuals[j]->depth >= visuals[i]->depth)
198 {
199 if ((visuals[j]->depth == 8) && (visuals[i]->depth == 8))
200 {
201 if (visuals[j]->type == GDK_VISUAL_PSEUDO_COLOR)
202 {
203 temp_visual = visuals[j];
204 visuals[j] = visuals[i];
205 visuals[i] = temp_visual;
206 }
207 else if ((visuals[i]->type != GDK_VISUAL_PSEUDO_COLOR) &&
208 visuals[j]->type > visuals[i]->type)
209 {
210 temp_visual = visuals[j];
211 visuals[j] = visuals[i];
212 visuals[i] = temp_visual;
213 }
214 }
215 else if ((visuals[j]->depth > visuals[i]->depth) ||
216 ((visuals[j]->depth == visuals[i]->depth) &&
217 (visuals[j]->type > visuals[i]->type)))
218 {
219 temp_visual = visuals[j];
220 visuals[j] = visuals[i];
221 visuals[i] = temp_visual;
222 }
223 }
224 }
225 }
226
227 for (i = 0; i < nvisuals; i++)
228 {
229 if (default_xvisual->visualid == GDK_X11_VISUAL (visuals[i])->xvisual->visualid)
230 {
231 x11_screen->system_visual = visuals[i];
232 GDK_X11_VISUAL (visuals[i])->colormap =
233 DefaultColormap (x11_screen->xdisplay, x11_screen->screen_num);
234 }
235
236 /* For now, we only support 8888 ARGB for the "rgba visual".
237 * Additional formats (like ABGR) could be added later if they
238 * turn up.
239 */
240 if (x11_screen->rgba_visual == NULL &&
241 visuals[i]->depth == 32 &&
242 (visuals[i]->red_mask == 0xff0000 &&
243 visuals[i]->green_mask == 0x00ff00 &&
244 visuals[i]->blue_mask == 0x0000ff))
245 {
246 x11_screen->rgba_visual = visuals[i];
247 }
248 }
249
250 #ifdef G_ENABLE_DEBUG
251 if (GDK_DEBUG_CHECK (MISC))
252 {
253 static const gchar *const visual_names[] =
254 {
255 "static gray",
256 "grayscale",
257 "static color",
258 "pseudo color",
259 "true color",
260 "direct color",
261 };
262
263 for (i = 0; i < nvisuals; i++)
264 g_message ("visual: %s: %d", visual_names[visuals[i]->type], visuals[i]->depth);
265 }
266 #endif /* G_ENABLE_DEBUG */
267
268 x11_screen->navailable_depths = 0;
269 for (i = 0; i < G_N_ELEMENTS (possible_depths); i++)
270 {
271 for (j = 0; j < nvisuals; j++)
272 {
273 if (visuals[j]->depth == possible_depths[i])
274 {
275 x11_screen->available_depths[x11_screen->navailable_depths++] = visuals[j]->depth;
276 break;
277 }
278 }
279 }
280
281 if (x11_screen->navailable_depths == 0)
282 g_error ("unable to find a usable depth");
283
284 x11_screen->navailable_types = 0;
285 for (i = 0; i < G_N_ELEMENTS (possible_types); i++)
286 {
287 for (j = 0; j < nvisuals; j++)
288 {
289 if (visuals[j]->type == possible_types[i])
290 {
291 x11_screen->available_types[x11_screen->navailable_types++] = visuals[j]->type;
292 break;
293 }
294 }
295 }
296
297 for (i = 0; i < nvisuals; i++)
298 gdk_visual_add (visuals[i]);
299
300 if (x11_screen->navailable_types == 0)
301 g_error ("unable to find a usable visual type");
302
303 x11_screen->visuals = visuals;
304 x11_screen->nvisuals = nvisuals;
305
306 /* If GL is available we want to pick better default/rgba visuals,
307 as we care about glx details such as alpha/depth/stencil depth,
308 stereo and double buffering */
309 _gdk_x11_screen_update_visuals_for_gl (screen);
310 }
311
312 gint
_gdk_x11_screen_visual_get_best_depth(GdkScreen * screen)313 _gdk_x11_screen_visual_get_best_depth (GdkScreen *screen)
314 {
315 return GDK_X11_SCREEN (screen)->available_depths[0];
316 }
317
318 GdkVisualType
_gdk_x11_screen_visual_get_best_type(GdkScreen * screen)319 _gdk_x11_screen_visual_get_best_type (GdkScreen *screen)
320 {
321 return GDK_X11_SCREEN (screen)->available_types[0];
322 }
323
324 GdkVisual *
_gdk_x11_screen_get_system_visual(GdkScreen * screen)325 _gdk_x11_screen_get_system_visual (GdkScreen *screen)
326 {
327 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
328
329 return ((GdkVisual *) GDK_X11_SCREEN (screen)->system_visual);
330 }
331
332 GdkVisual*
_gdk_x11_screen_visual_get_best(GdkScreen * screen)333 _gdk_x11_screen_visual_get_best (GdkScreen *screen)
334 {
335 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
336
337 return x11_screen->visuals[0];
338 }
339
340 GdkVisual*
_gdk_x11_screen_visual_get_best_with_depth(GdkScreen * screen,gint depth)341 _gdk_x11_screen_visual_get_best_with_depth (GdkScreen *screen,
342 gint depth)
343 {
344 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
345 GdkVisual *return_val;
346 int i;
347
348 return_val = NULL;
349 for (i = 0; i < x11_screen->nvisuals; i++)
350 if (depth == x11_screen->visuals[i]->depth)
351 {
352 return_val = x11_screen->visuals[i];
353 break;
354 }
355
356 return return_val;
357 }
358
359 GdkVisual*
_gdk_x11_screen_visual_get_best_with_type(GdkScreen * screen,GdkVisualType visual_type)360 _gdk_x11_screen_visual_get_best_with_type (GdkScreen *screen,
361 GdkVisualType visual_type)
362 {
363 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
364 GdkVisual *return_val;
365 int i;
366
367 return_val = NULL;
368 for (i = 0; i < x11_screen->nvisuals; i++)
369 if (visual_type == x11_screen->visuals[i]->type)
370 {
371 return_val = x11_screen->visuals[i];
372 break;
373 }
374
375 return return_val;
376 }
377
378 GdkVisual*
_gdk_x11_screen_visual_get_best_with_both(GdkScreen * screen,gint depth,GdkVisualType visual_type)379 _gdk_x11_screen_visual_get_best_with_both (GdkScreen *screen,
380 gint depth,
381 GdkVisualType visual_type)
382 {
383 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
384 GdkVisual *return_val;
385 int i;
386
387 return_val = NULL;
388 for (i = 0; i < x11_screen->nvisuals; i++)
389 if ((depth == x11_screen->visuals[i]->depth) &&
390 (visual_type == x11_screen->visuals[i]->type))
391 {
392 return_val = x11_screen->visuals[i];
393 break;
394 }
395
396 return return_val;
397 }
398
399 void
_gdk_x11_screen_query_depths(GdkScreen * screen,gint ** depths,gint * count)400 _gdk_x11_screen_query_depths (GdkScreen *screen,
401 gint **depths,
402 gint *count)
403 {
404 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
405
406 *count = x11_screen->navailable_depths;
407 *depths = x11_screen->available_depths;
408 }
409
410 void
_gdk_x11_screen_query_visual_types(GdkScreen * screen,GdkVisualType ** visual_types,gint * count)411 _gdk_x11_screen_query_visual_types (GdkScreen *screen,
412 GdkVisualType **visual_types,
413 gint *count)
414 {
415 GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
416
417 *count = x11_screen->navailable_types;
418 *visual_types = x11_screen->available_types;
419 }
420
421 GList *
_gdk_x11_screen_list_visuals(GdkScreen * screen)422 _gdk_x11_screen_list_visuals (GdkScreen *screen)
423 {
424 GList *list;
425 GdkX11Screen *x11_screen;
426 guint i;
427
428 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
429 x11_screen = GDK_X11_SCREEN (screen);
430
431 list = NULL;
432
433 for (i = 0; i < x11_screen->nvisuals; ++i)
434 list = g_list_append (list, x11_screen->visuals[i]);
435
436 return list;
437 }
438
439 /**
440 * gdk_x11_screen_lookup_visual:
441 * @screen: (type GdkX11Screen): a #GdkScreen.
442 * @xvisualid: an X Visual ID.
443 *
444 * Looks up the #GdkVisual for a particular screen and X Visual ID.
445 *
446 * Returns: (transfer none) (type GdkX11Visual): the #GdkVisual (owned by the screen
447 * object), or %NULL if the visual ID wasn’t found.
448 *
449 * Since: 2.2
450 */
451 GdkVisual *
gdk_x11_screen_lookup_visual(GdkScreen * screen,VisualID xvisualid)452 gdk_x11_screen_lookup_visual (GdkScreen *screen,
453 VisualID xvisualid)
454 {
455 int i;
456 GdkX11Screen *x11_screen;
457 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
458 x11_screen = GDK_X11_SCREEN (screen);
459
460 for (i = 0; i < x11_screen->nvisuals; i++)
461 if (xvisualid == GDK_X11_VISUAL (x11_screen->visuals[i])->xvisual->visualid)
462 return x11_screen->visuals[i];
463
464 return NULL;
465 }
466
467 static void
gdk_visual_add(GdkVisual * visual)468 gdk_visual_add (GdkVisual *visual)
469 {
470 GdkX11Screen *x11_screen = GDK_X11_SCREEN (visual->screen);
471
472 if (!x11_screen->visual_hash)
473 x11_screen->visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
474 (GEqualFunc) gdk_visual_equal);
475
476 g_hash_table_insert (x11_screen->visual_hash, GDK_X11_VISUAL (visual)->xvisual, visual);
477 }
478
479 static guint
gdk_visual_hash(Visual * key)480 gdk_visual_hash (Visual *key)
481 {
482 return key->visualid;
483 }
484
485 static gboolean
gdk_visual_equal(Visual * a,Visual * b)486 gdk_visual_equal (Visual *a,
487 Visual *b)
488 {
489 return (a->visualid == b->visualid);
490 }
491
492 /**
493 * _gdk_visual_get_x11_colormap:
494 * @visual: the visual to get the colormap from
495 *
496 * Gets the colormap to use
497 *
498 * Returns: the X Colormap to use for new windows using @visual
499 **/
500 Colormap
_gdk_visual_get_x11_colormap(GdkVisual * visual)501 _gdk_visual_get_x11_colormap (GdkVisual *visual)
502 {
503 GdkX11Visual *x11_visual;
504
505 g_return_val_if_fail (GDK_IS_VISUAL (visual), None);
506
507 x11_visual = GDK_X11_VISUAL (visual);
508
509 if (x11_visual->colormap == None)
510 {
511 x11_visual->colormap = XCreateColormap (GDK_SCREEN_XDISPLAY (visual->screen),
512 GDK_SCREEN_XROOTWIN (visual->screen),
513 x11_visual->xvisual,
514 AllocNone);
515 }
516
517 return x11_visual->colormap;
518 }
519
520 /**
521 * gdk_x11_visual_get_xvisual:
522 * @visual: (type GdkX11Visual): a #GdkVisual.
523 *
524 * Returns the X visual belonging to a #GdkVisual.
525 *
526 * Returns: (transfer none): an Xlib Visual*.
527 **/
528 Visual *
gdk_x11_visual_get_xvisual(GdkVisual * visual)529 gdk_x11_visual_get_xvisual (GdkVisual *visual)
530 {
531 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
532
533 return GDK_X11_VISUAL (visual)->xvisual;
534 }
535