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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. 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/.
30 #include "gdkinternals.h"
32 #include "gdkprivate-x11.h"
33 #include "gdkscreen-x11.h"
35 typedef struct _GdkColormapPrivateX11 GdkColormapPrivateX11;
37 struct _GdkColormapPrivateX11
45 time_t last_sync_time;
50 #define GDK_COLORMAP_PRIVATE_DATA(cmap) ((GdkColormapPrivateX11 *) GDK_COLORMAP (cmap)->windowing_data)
52 static gint gdk_colormap_match_color (GdkColormap *cmap,
54 const gchar *available);
55 static void gdk_colormap_add (GdkColormap *cmap);
56 static void gdk_colormap_remove (GdkColormap *cmap);
58 static GdkColormap *gdk_colormap_lookup (GdkScreen *screen,
61 static guint gdk_colormap_hash (Colormap *cmap);
62 static gboolean gdk_colormap_equal (Colormap *a,
64 static void gdk_colormap_sync (GdkColormap *colormap,
67 static void gdk_colormap_init (GdkColormap *colormap);
68 static void gdk_colormap_class_init (GdkColormapClass *klass);
69 static void gdk_colormap_finalize (GObject *object);
71 static gpointer parent_class = NULL;
74 gdk_colormap_get_type (void)
76 static GType object_type = 0;
80 static const GTypeInfo object_info =
82 sizeof (GdkColormapClass),
84 (GBaseFinalizeFunc) NULL,
85 (GClassInitFunc) gdk_colormap_class_init,
86 NULL, /* class_finalize */
87 NULL, /* class_data */
90 (GInstanceInitFunc) gdk_colormap_init,
93 object_type = g_type_register_static (G_TYPE_OBJECT,
102 gdk_colormap_init (GdkColormap *colormap)
104 GdkColormapPrivateX11 *private;
106 private = g_new (GdkColormapPrivateX11, 1);
108 colormap->windowing_data = private;
110 private->screen = NULL;
111 private->hash = NULL;
112 private->last_sync_time = 0;
113 private->info = NULL;
116 colormap->colors = NULL;
120 gdk_colormap_class_init (GdkColormapClass *klass)
122 GObjectClass *object_class = G_OBJECT_CLASS (klass);
124 parent_class = g_type_class_peek_parent (klass);
126 object_class->finalize = gdk_colormap_finalize;
130 gdk_colormap_finalize (GObject *object)
132 GdkColormap *colormap = GDK_COLORMAP (object);
133 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
135 gdk_colormap_remove (colormap);
137 if (!private->screen->closed)
138 XFreeColormap (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap);
141 g_hash_table_destroy (private->hash);
143 g_free (private->info);
144 g_free (colormap->colors);
147 G_OBJECT_CLASS (parent_class)->finalize (object);
152 * @visual: a #GdkVisual.
153 * @allocate: if %TRUE, the newly created colormap will be
154 * a private colormap, and all colors in it will be
155 * allocated for the applications use.
157 * Creates a new colormap for the given visual.
159 * Return value: the new #GdkColormap.
162 gdk_colormap_new (GdkVisual *visual,
165 GdkColormap *colormap;
166 GdkColormapPrivateX11 *private;
173 /* FIXME when object properties settle down, there needs to be some
174 * kind of default construction (and construct-only arguments)
177 g_return_val_if_fail (visual != NULL, NULL);
179 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
180 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
182 colormap->visual = visual;
183 private->screen = gdk_visual_get_screen (visual);
185 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
186 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
187 xrootwin = GDK_SCREEN_XROOTWIN (private->screen);
189 colormap->size = visual->colormap_size;
191 switch (visual->type)
193 case GDK_VISUAL_GRAYSCALE:
194 case GDK_VISUAL_PSEUDO_COLOR:
195 private->info = g_new0 (GdkColorInfo, colormap->size);
196 colormap->colors = g_new (GdkColor, colormap->size);
198 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
199 (GEqualFunc) gdk_color_equal);
201 private->private_val = allocate;
202 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
203 xvisual, (allocate) ? (AllocAll) : (AllocNone));
207 GdkVisual *system_visual;
208 XColor *default_colors;
209 gint n_default_colors;
211 system_visual = gdk_screen_get_system_visual (private->screen);
212 n_default_colors = MIN (system_visual->colormap_size, colormap->size);
214 default_colors = g_new (XColor, colormap->size);
216 for (i = 0; i < n_default_colors; i++)
217 default_colors[i].pixel = i;
219 XQueryColors (xdisplay,
220 DefaultColormapOfScreen (GDK_SCREEN_X11 (private->screen)->xscreen),
221 default_colors, n_default_colors);
223 for (i = 0; i < n_default_colors; i++)
225 colormap->colors[i].pixel = default_colors[i].pixel;
226 colormap->colors[i].red = default_colors[i].red;
227 colormap->colors[i].green = default_colors[i].green;
228 colormap->colors[i].blue = default_colors[i].blue;
231 gdk_colormap_change (colormap, n_default_colors);
233 g_free (default_colors);
237 case GDK_VISUAL_DIRECT_COLOR:
238 private->private_val = TRUE;
239 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
241 colormap->colors = g_new (GdkColor, colormap->size);
243 size = 1 << visual->red_prec;
244 for (i = 0; i < size; i++)
245 colormap->colors[i].red = i * 65535 / (size - 1);
247 size = 1 << visual->green_prec;
248 for (i = 0; i < size; i++)
249 colormap->colors[i].green = i * 65535 / (size - 1);
251 size = 1 << visual->blue_prec;
252 for (i = 0; i < size; i++)
253 colormap->colors[i].blue = i * 65535 / (size - 1);
255 gdk_colormap_change (colormap, colormap->size);
258 case GDK_VISUAL_STATIC_GRAY:
259 case GDK_VISUAL_STATIC_COLOR:
260 private->private_val = FALSE;
261 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
264 colormap->colors = g_new (GdkColor, colormap->size);
265 gdk_colormap_sync (colormap, TRUE);
268 case GDK_VISUAL_TRUE_COLOR:
269 private->private_val = FALSE;
270 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
275 gdk_colormap_add (colormap);
281 gdk_colormap_sync_palette (GdkColormap *colormap)
283 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
289 xpalette = g_new (XColor, colormap->size);
291 for (i = 0; i < colormap->size; i++)
293 if (!private->info || private->info[i].ref_count == 0)
295 xpalette[nlookup].pixel = i;
296 xpalette[nlookup].red = 0;
297 xpalette[nlookup].green = 0;
298 xpalette[nlookup].blue = 0;
303 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
304 private->xcolormap, xpalette, nlookup);
306 for (i = 0; i < nlookup; i++)
308 gulong pixel = xpalette[i].pixel;
309 colormap->colors[pixel].pixel = pixel;
310 colormap->colors[pixel].red = xpalette[i].red;
311 colormap->colors[pixel].green = xpalette[i].green;
312 colormap->colors[pixel].blue = xpalette[i].blue;
319 gdk_colormap_sync_direct_color (GdkColormap *colormap)
321 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
322 GdkVisual *visual = colormap->visual;
326 xpalette = g_new (XColor, colormap->size);
328 for (i = 0; i < colormap->size; i++)
331 (((i << visual->red_shift) & visual->red_mask) |
332 ((i << visual->green_shift) & visual->green_mask) |
333 ((i << visual->blue_shift) & visual->blue_mask));
336 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
337 private->xcolormap, xpalette, colormap->size);
339 for (i = 0; i < colormap->size; i++)
341 colormap->colors[i].pixel = xpalette[i].pixel;
342 colormap->colors[i].red = xpalette[i].red;
343 colormap->colors[i].green = xpalette[i].green;
344 colormap->colors[i].blue = xpalette[i].blue;
350 #define MIN_SYNC_TIME 2
353 gdk_colormap_sync (GdkColormap *colormap,
357 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
359 g_return_if_fail (GDK_IS_COLORMAP (colormap));
361 if (private->screen->closed)
364 current_time = time (NULL);
365 if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
368 private->last_sync_time = current_time;
370 if (colormap->visual->type == GDK_VISUAL_DIRECT_COLOR)
371 gdk_colormap_sync_direct_color (colormap);
373 gdk_colormap_sync_palette (colormap);
377 * gdk_screen_get_system_colormap:
378 * @screen: a #GdkScreen
380 * Gets the system's default colormap for @screen
382 * Returns: the default colormap for @screen.
387 gdk_screen_get_system_colormap (GdkScreen *screen)
389 GdkColormap *colormap = NULL;
390 GdkColormapPrivateX11 *private;
391 GdkScreenX11 *screen_x11;
393 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
394 screen_x11 = GDK_SCREEN_X11 (screen);
396 if (screen_x11->system_colormap)
397 return screen_x11->system_colormap;
399 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
400 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
402 private->screen = screen;
403 colormap->visual = gdk_screen_get_system_visual (screen);
405 private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
406 private->private_val = FALSE;
408 private->hash = NULL;
409 private->last_sync_time = 0;
410 private->info = NULL;
412 colormap->colors = NULL;
413 colormap->size = colormap->visual->colormap_size;
415 switch (colormap->visual->type)
417 case GDK_VISUAL_GRAYSCALE:
418 case GDK_VISUAL_PSEUDO_COLOR:
419 private->info = g_new0 (GdkColorInfo, colormap->size);
420 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
421 (GEqualFunc) gdk_color_equal);
423 case GDK_VISUAL_STATIC_GRAY:
424 case GDK_VISUAL_STATIC_COLOR:
425 case GDK_VISUAL_DIRECT_COLOR:
426 colormap->colors = g_new (GdkColor, colormap->size);
427 gdk_colormap_sync (colormap, TRUE);
429 case GDK_VISUAL_TRUE_COLOR:
433 gdk_colormap_add (colormap);
434 screen_x11->system_colormap = colormap;
440 * gdk_colormap_get_system_size:
442 * Returns the size of the system's default colormap.
443 * (See the description of struct #GdkColormap for an
444 * explanation of the size of a colormap.)
446 * Return value: the size of the system's default colormap.
449 gdk_colormap_get_system_size (void)
451 return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
452 GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
456 * gdk_colormap_change:
457 * @colormap: a #GdkColormap.
458 * @ncolors: the number of colors to change.
460 * Changes the value of the first @ncolors in a private colormap
461 * to match the values in the <structfield>colors</structfield>
462 * array in the colormap. This function is obsolete and
463 * should not be used. See gdk_color_change().
466 gdk_colormap_change (GdkColormap *colormap,
469 GdkColormapPrivateX11 *private;
478 g_return_if_fail (GDK_IS_COLORMAP (colormap));
480 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
482 if (private->screen->closed)
485 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
486 palette = g_new (XColor, ncolors);
488 switch (colormap->visual->type)
490 case GDK_VISUAL_GRAYSCALE:
491 case GDK_VISUAL_PSEUDO_COLOR:
492 for (i = 0; i < ncolors; i++)
494 palette[i].pixel = colormap->colors[i].pixel;
495 palette[i].red = colormap->colors[i].red;
496 palette[i].green = colormap->colors[i].green;
497 palette[i].blue = colormap->colors[i].blue;
498 palette[i].flags = DoRed | DoGreen | DoBlue;
501 XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
504 case GDK_VISUAL_DIRECT_COLOR:
505 visual = colormap->visual;
507 shift = visual->red_shift;
508 max_colors = 1 << visual->red_prec;
509 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
511 for (i = 0; i < size; i++)
513 palette[i].pixel = i << shift;
514 palette[i].red = colormap->colors[i].red;
515 palette[i].flags = DoRed;
518 XStoreColors (xdisplay, private->xcolormap, palette, size);
520 shift = visual->green_shift;
521 max_colors = 1 << visual->green_prec;
522 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
524 for (i = 0; i < size; i++)
526 palette[i].pixel = i << shift;
527 palette[i].green = colormap->colors[i].green;
528 palette[i].flags = DoGreen;
531 XStoreColors (xdisplay, private->xcolormap, palette, size);
533 shift = visual->blue_shift;
534 max_colors = 1 << visual->blue_prec;
535 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
537 for (i = 0; i < size; i++)
539 palette[i].pixel = i << shift;
540 palette[i].blue = colormap->colors[i].blue;
541 palette[i].flags = DoBlue;
544 XStoreColors (xdisplay, private->xcolormap, palette, size);
556 * @colormap: a #GdkColormap.
557 * @contiguous: if %TRUE, the colors should be allocated
558 * in contiguous color cells.
559 * @planes: an array in which to store the plane masks.
560 * @nplanes: the number of planes to allocate. (Or zero,
561 * to indicate that the color allocation should not be planar.)
562 * @pixels: an array into which to store allocated pixel values.
563 * @npixels: the number of pixels in each plane to allocate.
565 * Allocates colors from a colormap. This function
566 * is obsolete. See gdk_colormap_alloc_colors().
567 * For full documentation of the fields, see
568 * the Xlib documentation for <function>XAllocColorCells()</function>.
573 gdk_colors_alloc (GdkColormap *colormap,
580 GdkColormapPrivateX11 *private;
584 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
586 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
588 if (private->screen->closed)
591 return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
592 private->xcolormap,contiguous, planes,
593 nplanes, pixels, npixels);
596 for (i=0; i<npixels; i++)
598 private->info[pixels[i]].ref_count++;
599 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
603 return return_val != 0;
606 /* This is almost identical to gdk_colormap_free_colors.
613 * @colormap: a #GdkColormap.
614 * @pixels: the pixel values of the colors to free.
615 * @npixels: the number of values in @pixels.
616 * @planes: the plane masks for all planes to free, OR'd together.
618 * Frees colors allocated with gdk_colors_alloc(). This
619 * function is obsolete. See gdk_colormap_free_colors().
622 gdk_colors_free (GdkColormap *colormap,
627 GdkColormapPrivateX11 *private;
628 gulong *pixels_to_free;
629 gint npixels_to_free = 0;
632 g_return_if_fail (GDK_IS_COLORMAP (colormap));
633 g_return_if_fail (pixels != NULL);
635 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
637 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
638 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
641 pixels_to_free = g_new (gulong, npixels);
643 for (i=0; i<npixels; i++)
645 gulong pixel = pixels[i];
647 if (private->info[pixel].ref_count)
649 private->info[pixel].ref_count--;
651 if (private->info[pixel].ref_count == 0)
653 pixels_to_free[npixels_to_free++] = pixel;
654 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
655 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
656 private->info[pixel].flags = 0;
661 if (npixels_to_free && !private->private_val && !private->screen->closed)
662 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
663 pixels_to_free, npixels_to_free, planes);
664 g_free (pixels_to_free);
667 /* This is almost identical to gdk_colors_free.
672 * gdk_colormap_free_colors:
673 * @colormap: a #GdkColormap.
674 * @colors: the colors to free.
675 * @ncolors: the number of colors in @colors.
677 * Frees previously allocated colors.
680 gdk_colormap_free_colors (GdkColormap *colormap,
684 GdkColormapPrivateX11 *private;
689 g_return_if_fail (GDK_IS_COLORMAP (colormap));
690 g_return_if_fail (colors != NULL);
692 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
694 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
695 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
698 pixels = g_new (gulong, ncolors);
700 for (i=0; i<ncolors; i++)
702 gulong pixel = colors[i].pixel;
704 if (private->info[pixel].ref_count)
706 private->info[pixel].ref_count--;
708 if (private->info[pixel].ref_count == 0)
710 pixels[npixels++] = pixel;
711 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
712 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
713 private->info[pixel].flags = 0;
718 if (npixels && !private->private_val && !private->screen->closed)
719 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
725 /********************
727 ********************/
729 /* Try to allocate a single color using XAllocColor. If it succeeds,
730 * cache the result in our colormap, and store in ret.
733 gdk_colormap_alloc1 (GdkColormap *colormap,
737 GdkColormapPrivateX11 *private;
740 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
742 xcolor.red = color->red;
743 xcolor.green = color->green;
744 xcolor.blue = color->blue;
745 xcolor.pixel = color->pixel;
746 xcolor.flags = DoRed | DoGreen | DoBlue;
748 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
750 ret->pixel = xcolor.pixel;
751 ret->red = xcolor.red;
752 ret->green = xcolor.green;
753 ret->blue = xcolor.blue;
755 if (ret->pixel < colormap->size)
757 if (private->info[ret->pixel].ref_count) /* got a duplicate */
759 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
760 &xcolor.pixel, 1, 0);
761 private->info[ret->pixel].ref_count++;
765 colormap->colors[ret->pixel] = *color;
766 colormap->colors[ret->pixel].pixel = ret->pixel;
767 private->info[ret->pixel].ref_count = 1;
769 g_hash_table_insert (private->hash,
770 &colormap->colors[ret->pixel],
771 &colormap->colors[ret->pixel]);
783 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
790 GdkColormapPrivateX11 *private;
795 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
797 if (private->private_val)
800 for (i=0; i<ncolors; i++)
802 while ((index < colormap->size) && (private->info[index].ref_count != 0))
805 if (index < colormap->size)
807 colors[i].pixel = index;
809 private->info[index].ref_count++;
810 private->info[i].flags |= GDK_COLOR_WRITEABLE;
819 pixels = g_new (gulong, ncolors);
820 /* Allocation of a writeable color cells */
822 status = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
823 FALSE, NULL, 0, pixels, ncolors);
826 for (i=0; i<ncolors; i++)
828 colors[i].pixel = pixels[i];
830 private->info[pixels[i]].ref_count++;
831 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
837 return status ? 0 : ncolors;
842 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
849 GdkColormapPrivateX11 *private;
851 XColor *store = g_new (XColor, ncolors);
855 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
857 /* First, store the colors we have room for */
860 for (i=0; i<ncolors; i++)
864 while ((index < colormap->size) && (private->info[index].ref_count != 0))
867 if (index < colormap->size)
869 store[nstore].red = colors[i].red;
870 store[nstore].blue = colors[i].blue;
871 store[nstore].green = colors[i].green;
872 store[nstore].pixel = index;
873 store[nstore].flags = DoRed | DoGreen | DoBlue;
877 colors[i].pixel = index;
879 colormap->colors[i] = colors[i];
880 private->info[index].ref_count++;
882 g_hash_table_insert (private->hash,
883 &colormap->colors[index],
884 &colormap->colors[index]);
891 XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
895 if (nremaining > 0 && best_match)
897 /* Get best matches for remaining colors */
899 gchar *available = g_new (gchar, colormap->size);
900 for (i = 0; i < colormap->size; i++)
901 available[i] = !(private->info[i].flags & GDK_COLOR_WRITEABLE);
903 for (i=0; i<ncolors; i++)
907 index = gdk_colormap_match_color (colormap,
912 colors[i] = colormap->colors[index];
913 private->info[index].ref_count++;
927 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
934 GdkColormapPrivateX11 *private;
939 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
941 for (i=0; i<ncolors; i++)
945 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
953 if (nremaining > 0 && best_match)
955 gchar *available = g_new (gchar, colormap->size);
956 for (i = 0; i < colormap->size; i++)
957 available[i] = ((private->info[i].ref_count == 0) ||
958 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
959 gdk_colormap_sync (colormap, FALSE);
961 while (nremaining > 0)
963 for (i=0; i<ncolors; i++)
967 index = gdk_colormap_match_color (colormap, &colors[i], available);
970 if (private->info[index].ref_count)
972 private->info[index].ref_count++;
973 colors[i] = colormap->colors[index];
979 if (gdk_colormap_alloc1 (colormap,
980 &colormap->colors[index],
989 available[index] = FALSE;
997 success[i] = 2; /* flag as permanent failure */
1005 /* Change back the values we flagged as permanent failures */
1008 for (i=0; i<ncolors; i++)
1009 if (success[i] == 2)
1011 nremaining = nfailed;
1018 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1022 gboolean best_match,
1025 GdkColormapPrivateX11 *private;
1026 GdkColor *lookup_color;
1028 gint nremaining = 0;
1030 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1032 /* Check for an exact match among previously allocated colors */
1034 for (i=0; i<ncolors; i++)
1038 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1041 private->info[lookup_color->pixel].ref_count++;
1042 colors[i].pixel = lookup_color->pixel;
1050 /* If that failed, we try to allocate a new color, or approxmiate
1051 * with what we can get if best_match is TRUE.
1055 if (private->private_val)
1056 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1058 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1065 * gdk_colormap_alloc_colors:
1066 * @colormap: a #GdkColormap.
1067 * @colors: The color values to allocate. On return, the pixel
1068 * values for allocated colors will be filled in.
1069 * @ncolors: The number of colors in @colors.
1070 * @writeable: If %TRUE, the colors are allocated writeable
1071 * (their values can later be changed using gdk_color_change()).
1072 * Writeable colors cannot be shared between applications.
1073 * @best_match: If %TRUE, GDK will attempt to do matching against
1074 * existing colors if the colors cannot be allocated as requested.
1075 * @success: An array of length @ncolors. On return, this
1076 * indicates whether the corresponding color in @colors was
1077 * sucessfully allocated or not.
1079 * Allocates colors from a colormap.
1081 * Return value: The number of colors that were not sucessfully
1085 gdk_colormap_alloc_colors (GdkColormap *colormap,
1089 gboolean best_match,
1092 GdkColormapPrivateX11 *private;
1095 gint nremaining = 0;
1098 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
1099 g_return_val_if_fail (colors != NULL, ncolors);
1101 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1103 if (private->screen->closed)
1106 for (i=0; i<ncolors; i++)
1111 switch (colormap->visual->type)
1113 case GDK_VISUAL_PSEUDO_COLOR:
1114 case GDK_VISUAL_GRAYSCALE:
1116 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1117 writeable, best_match, success);
1119 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1120 writeable, best_match, success);
1123 case GDK_VISUAL_DIRECT_COLOR:
1124 case GDK_VISUAL_TRUE_COLOR:
1125 visual = colormap->visual;
1127 for (i=0; i<ncolors; i++)
1129 colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1130 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1131 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1135 case GDK_VISUAL_STATIC_GRAY:
1136 case GDK_VISUAL_STATIC_COLOR:
1137 for (i=0; i<ncolors; i++)
1139 xcolor.red = colors[i].red;
1140 xcolor.green = colors[i].green;
1141 xcolor.blue = colors[i].blue;
1142 xcolor.pixel = colors[i].pixel;
1143 xcolor.flags = DoRed | DoGreen | DoBlue;
1145 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1147 colors[i].pixel = xcolor.pixel;
1159 * gdk_colormap_query_color:
1160 * @colormap: a #GdkColormap
1161 * @pixel: pixel value in hardware display format
1162 * @result: #GdkColor with red, green, blue fields initialized
1164 * Locates the RGB color in @colormap corresponding to the given
1165 * hardware pixel @pixel. @pixel must be a valid pixel in the
1166 * colormap; it's a programmer error to call this function with a
1167 * pixel which is not in the colormap. Hardware pixels are normally
1168 * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1169 * #GdkImage contains image data in hardware format, a #GdkPixbuf
1170 * contains image data in a canonical 24-bit RGB format.)
1172 * This function is rarely useful; it's used for example to
1173 * implement the eyedropper feature in #GtkColorSelection.
1177 gdk_colormap_query_color (GdkColormap *colormap,
1183 GdkColormapPrivateX11 *private;
1185 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1187 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1189 visual = gdk_colormap_get_visual (colormap);
1191 switch (visual->type) {
1192 case GDK_VISUAL_DIRECT_COLOR:
1193 case GDK_VISUAL_TRUE_COLOR:
1194 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1195 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1196 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1198 case GDK_VISUAL_STATIC_GRAY:
1199 case GDK_VISUAL_GRAYSCALE:
1200 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1202 case GDK_VISUAL_STATIC_COLOR:
1203 xcolor.pixel = pixel;
1204 if (!private->screen->closed)
1206 XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1207 result->red = xcolor.red;
1208 result->green = xcolor.green;
1209 result->blue = xcolor.blue;
1212 result->red = result->green = result->blue = 0;
1214 case GDK_VISUAL_PSEUDO_COLOR:
1215 g_return_if_fail (pixel < colormap->size);
1216 result->red = colormap->colors[pixel].red;
1217 result->green = colormap->colors[pixel].green;
1218 result->blue = colormap->colors[pixel].blue;
1221 g_assert_not_reached ();
1228 * @colormap: a #GdkColormap.
1229 * @color: a #GdkColor, with the color to change
1230 * in the <structfield>pixel</structfield> field,
1231 * and the new value in the remaining fields.
1233 * Changes the value of a color that has already
1234 * been allocated. If @colormap is not a private
1235 * colormap, then the color must have been allocated
1236 * using gdk_colormap_alloc_colors() with the
1237 * @writeable set to %TRUE.
1239 * Return value: %TRUE if the color was successfully changed.
1242 gdk_color_change (GdkColormap *colormap,
1245 GdkColormapPrivateX11 *private;
1248 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1249 g_return_val_if_fail (color != NULL, FALSE);
1251 xcolor.pixel = color->pixel;
1252 xcolor.red = color->red;
1253 xcolor.green = color->green;
1254 xcolor.blue = color->blue;
1255 xcolor.flags = DoRed | DoGreen | DoBlue;
1257 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1258 if (!private->screen->closed)
1259 XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1265 * gdk_x11_colormap_foreign_new:
1266 * @visual: a #GdkVisual
1267 * @xcolormap: The XID of a colormap with visual @visual
1269 * If xcolormap refers to a colormap previously known to GTK+,
1270 * returns a new reference to the existing #GdkColormap object,
1271 * otherwise creates a new GdkColormap object and returns that
1273 * Return value: the #GdkColormap object for @xcolormap.
1274 * Free with g_object_unref(). Note that for colormap created
1275 * with gdk_x11_colormap_foreign_new(), unref'ing the last
1276 * reference to the object will only free the #GdkColoramp
1277 * object and not call XFreeColormap()
1282 gdk_x11_colormap_foreign_new (GdkVisual *visual,
1285 GdkColormap *colormap;
1287 GdkColormapPrivateX11 *private;
1289 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
1290 g_return_val_if_fail (xcolormap != None, NULL);
1292 screen = gdk_visual_get_screen (visual);
1294 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1295 GDK_SCREEN_XNUMBER (screen)))
1296 return g_object_ref (gdk_screen_get_system_colormap (screen));
1298 colormap = gdk_colormap_lookup (screen, xcolormap);
1300 return g_object_ref (colormap);
1302 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
1303 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1305 colormap->visual = visual;
1307 private->screen = screen;
1308 private->xcolormap = xcolormap;
1309 private->private_val = FALSE;
1311 colormap->size = visual->colormap_size;
1313 switch (colormap->visual->type)
1315 case GDK_VISUAL_GRAYSCALE:
1316 case GDK_VISUAL_PSEUDO_COLOR:
1317 private->info = g_new0 (GdkColorInfo, colormap->size);
1318 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1319 (GEqualFunc) gdk_color_equal);
1321 case GDK_VISUAL_STATIC_GRAY:
1322 case GDK_VISUAL_STATIC_COLOR:
1323 case GDK_VISUAL_DIRECT_COLOR:
1324 colormap->colors = g_new (GdkColor, colormap->size);
1325 gdk_colormap_sync (colormap, TRUE);
1327 case GDK_VISUAL_TRUE_COLOR:
1331 gdk_colormap_add (colormap);
1338 * gdkx_colormap_get:
1339 * @xcolormap: the XID of a colormap for the default screen.
1341 * Returns a #GdkColormap corresponding to a X colormap;
1342 * this function only works if the colormap is already
1343 * known to GTK+ (a colormap created by GTK+ or the default
1344 * colormap for the screen), since GTK+
1346 * Always use gdk_x11_colormap_foreign_new() instead.
1348 * Return value: the existing #GdkColormap object if it was
1349 * already known to GTK+, otherwise warns and return
1353 gdkx_colormap_get (Colormap xcolormap)
1355 GdkScreen *screen = gdk_screen_get_default ();
1356 GdkColormap *colormap;
1358 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1359 GDK_SCREEN_XNUMBER (screen)));
1360 return g_object_ref (gdk_screen_get_system_colormap (screen));
1362 colormap = gdk_colormap_lookup (screen, xcolormap);
1364 return g_object_ref (colormap);
1366 g_warning ("Colormap passed to gdkx_colormap_get\n"
1367 "does not previously exist");
1373 gdk_colormap_match_color (GdkColormap *cmap,
1375 const gchar *available)
1379 gint rdiff, gdiff, bdiff;
1382 g_return_val_if_fail (cmap != NULL, 0);
1383 g_return_val_if_fail (color != NULL, 0);
1385 colors = cmap->colors;
1389 for (i = 0; i < cmap->size; i++)
1391 if ((!available) || (available && available[i]))
1393 rdiff = (color->red - colors[i].red);
1394 gdiff = (color->green - colors[i].green);
1395 bdiff = (color->blue - colors[i].blue);
1397 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1412 gdk_colormap_lookup (GdkScreen *screen,
1415 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1417 if (screen_x11->colormap_hash)
1418 return g_hash_table_lookup (screen_x11->colormap_hash, &xcolormap);
1424 gdk_colormap_add (GdkColormap *cmap)
1426 GdkScreenX11 *screen_x11;
1427 GdkColormapPrivateX11 *private;
1429 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1430 screen_x11 = GDK_SCREEN_X11 (private->screen);
1432 if (!screen_x11->colormap_hash)
1433 screen_x11->colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1434 (GEqualFunc) gdk_colormap_equal);
1436 g_hash_table_insert (screen_x11->colormap_hash, &private->xcolormap, cmap);
1440 gdk_colormap_remove (GdkColormap *cmap)
1442 GdkScreenX11 *screen_x11;
1443 GdkColormapPrivateX11 *private;
1445 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1446 screen_x11 = GDK_SCREEN_X11 (private->screen);
1448 if (screen_x11->colormap_hash)
1449 g_hash_table_remove (screen_x11->colormap_hash, &private->xcolormap);
1453 gdk_colormap_hash (Colormap *colormap)
1459 gdk_colormap_equal (Colormap *a,
1466 * gdk_x11_colormap_get_xdisplay:
1467 * @colormap: a #GdkColormap.
1469 * Returns the display of a #GdkColormap.
1471 * Return value: an Xlib <type>Display*</type>.
1474 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1476 GdkColormapPrivateX11 *private;
1478 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1480 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1482 return GDK_SCREEN_XDISPLAY (private->screen);
1486 * gdk_x11_colormap_get_xcolormap:
1487 * @colormap: a #GdkColormap.
1489 * Returns the X colormap belonging to a #GdkColormap.
1491 * Return value: an Xlib <type>Colormap</type>.
1494 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1496 GdkColormapPrivateX11 *private;
1498 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1500 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1502 if (private->screen->closed)
1505 return private->xcolormap;
1509 * gdk_colormap_get_screen:
1510 * @cmap: a #GdkColormap
1512 * Gets the screen for which this colormap was created.
1514 * Return value: the screen for which this colormap was created.
1519 gdk_colormap_get_screen (GdkColormap *cmap)
1521 g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1523 return GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;