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
46 time_t last_sync_time;
49 #define GDK_COLORMAP_PRIVATE_DATA(cmap) ((GdkColormapPrivateX11 *) GDK_COLORMAP (cmap)->windowing_data)
51 static gint gdk_colormap_match_color (GdkColormap *cmap,
53 const gchar *available);
54 static void gdk_colormap_add (GdkColormap *cmap);
55 static void gdk_colormap_remove (GdkColormap *cmap);
56 static guint gdk_colormap_hash (Colormap *cmap);
57 static gboolean gdk_colormap_equal (Colormap *a,
59 static void gdk_colormap_sync (GdkColormap *colormap,
62 static void gdk_colormap_init (GdkColormap *colormap);
63 static void gdk_colormap_class_init (GdkColormapClass *klass);
64 static void gdk_colormap_finalize (GObject *object);
66 static gpointer parent_class = NULL;
68 static GHashTable *colormap_hash = NULL;
71 gdk_colormap_get_type (void)
73 static GType object_type = 0;
77 static const GTypeInfo object_info =
79 sizeof (GdkColormapClass),
81 (GBaseFinalizeFunc) NULL,
82 (GClassInitFunc) gdk_colormap_class_init,
83 NULL, /* class_finalize */
84 NULL, /* class_data */
87 (GInstanceInitFunc) gdk_colormap_init,
90 object_type = g_type_register_static (G_TYPE_OBJECT,
99 gdk_colormap_init (GdkColormap *colormap)
101 GdkColormapPrivateX11 *private;
103 private = g_new (GdkColormapPrivateX11, 1);
105 colormap->windowing_data = private;
107 private->screen = NULL;
108 private->hash = NULL;
109 private->last_sync_time = 0;
110 private->info = NULL;
113 colormap->colors = NULL;
117 gdk_colormap_class_init (GdkColormapClass *klass)
119 GObjectClass *object_class = G_OBJECT_CLASS (klass);
121 parent_class = g_type_class_peek_parent (klass);
123 object_class->finalize = gdk_colormap_finalize;
127 gdk_colormap_finalize (GObject *object)
129 GdkColormap *colormap = GDK_COLORMAP (object);
130 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
132 gdk_colormap_remove (colormap);
134 if (!private->screen->closed)
135 XFreeColormap (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap);
138 g_hash_table_destroy (private->hash);
140 g_free (private->info);
141 g_free (colormap->colors);
143 G_OBJECT_CLASS (parent_class)->finalize (object);
147 gdk_colormap_new (GdkVisual *visual,
148 gboolean private_cmap)
150 GdkColormap *colormap;
151 GdkColormapPrivateX11 *private;
158 /* FIXME when object properties settle down, there needs to be some
159 * kind of default construction (and construct-only arguments)
162 g_return_val_if_fail (visual != NULL, NULL);
164 colormap = g_object_new (gdk_colormap_get_type (), NULL);
165 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
167 colormap->visual = visual;
168 private->screen = gdk_visual_get_screen (visual);
170 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
171 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
172 xrootwin = GDK_SCREEN_XROOTWIN (private->screen);
174 colormap->size = visual->colormap_size;
176 switch (visual->type)
178 case GDK_VISUAL_GRAYSCALE:
179 case GDK_VISUAL_PSEUDO_COLOR:
180 private->info = g_new0 (GdkColorInfo, colormap->size);
181 colormap->colors = g_new (GdkColor, colormap->size);
183 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
184 (GEqualFunc) gdk_color_equal);
186 private->private_val = private_cmap;
187 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
188 xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
192 XColor *default_colors;
194 default_colors = g_new (XColor, colormap->size);
196 for (i = 0; i < colormap->size; i++)
197 default_colors[i].pixel = i;
199 XQueryColors (xdisplay,
200 DefaultColormapOfScreen (GDK_SCREEN_X11 (private->screen)->xscreen),
201 default_colors, colormap->size);
203 for (i = 0; i < colormap->size; i++)
205 colormap->colors[i].pixel = default_colors[i].pixel;
206 colormap->colors[i].red = default_colors[i].red;
207 colormap->colors[i].green = default_colors[i].green;
208 colormap->colors[i].blue = default_colors[i].blue;
211 gdk_colormap_change (colormap, colormap->size);
213 g_free (default_colors);
217 case GDK_VISUAL_DIRECT_COLOR:
218 private->private_val = TRUE;
219 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
221 colormap->colors = g_new (GdkColor, colormap->size);
223 size = 1 << visual->red_prec;
224 for (i = 0; i < size; i++)
225 colormap->colors[i].red = i * 65535 / (size - 1);
227 size = 1 << visual->green_prec;
228 for (i = 0; i < size; i++)
229 colormap->colors[i].green = i * 65535 / (size - 1);
231 size = 1 << visual->blue_prec;
232 for (i = 0; i < size; i++)
233 colormap->colors[i].blue = i * 65535 / (size - 1);
235 gdk_colormap_change (colormap, colormap->size);
238 case GDK_VISUAL_STATIC_GRAY:
239 case GDK_VISUAL_STATIC_COLOR:
240 private->private_val = FALSE;
241 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
244 colormap->colors = g_new (GdkColor, colormap->size);
245 gdk_colormap_sync (colormap, TRUE);
248 case GDK_VISUAL_TRUE_COLOR:
249 private->private_val = FALSE;
250 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
255 gdk_colormap_add (colormap);
261 gdk_colormap_sync_palette (GdkColormap *colormap)
263 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
269 xpalette = g_new (XColor, colormap->size);
271 for (i = 0; i < colormap->size; i++)
273 if (!private->info || private->info[i].ref_count == 0)
275 xpalette[nlookup].pixel = i;
276 xpalette[nlookup].red = 0;
277 xpalette[nlookup].green = 0;
278 xpalette[nlookup].blue = 0;
283 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
284 private->xcolormap, xpalette, nlookup);
286 for (i = 0; i < nlookup; i++)
288 gulong pixel = xpalette[i].pixel;
289 colormap->colors[pixel].pixel = pixel;
290 colormap->colors[pixel].red = xpalette[i].red;
291 colormap->colors[pixel].green = xpalette[i].green;
292 colormap->colors[pixel].blue = xpalette[i].blue;
299 gdk_colormap_sync_direct_color (GdkColormap *colormap)
301 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
302 GdkVisual *visual = colormap->visual;
306 xpalette = g_new (XColor, colormap->size);
308 for (i = 0; i < colormap->size; i++)
311 (((i << visual->red_shift) & visual->red_mask) |
312 ((i << visual->green_shift) & visual->green_mask) |
313 ((i << visual->blue_shift) & visual->blue_mask));
316 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
317 private->xcolormap, xpalette, colormap->size);
319 for (i = 0; i < colormap->size; i++)
321 colormap->colors[i].pixel = xpalette[i].pixel;
322 colormap->colors[i].red = xpalette[i].red;
323 colormap->colors[i].green = xpalette[i].green;
324 colormap->colors[i].blue = xpalette[i].blue;
330 #define MIN_SYNC_TIME 2
333 gdk_colormap_sync (GdkColormap *colormap,
337 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
339 g_return_if_fail (GDK_IS_COLORMAP (colormap));
341 if (private->screen->closed)
344 current_time = time (NULL);
345 if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
348 private->last_sync_time = current_time;
350 if (colormap->visual->type == GDK_VISUAL_DIRECT_COLOR)
351 gdk_colormap_sync_direct_color (colormap);
353 gdk_colormap_sync_palette (colormap);
357 * gdk_screen_get_system_colormap:
358 * @screen: a #GdkScreen
360 * Gets the system's default colormap for @screen
362 * Returns: the default colormap for @screen.
365 gdk_screen_get_system_colormap (GdkScreen *screen)
367 GdkColormap *colormap = NULL;
368 GdkColormapPrivateX11 *private;
369 GdkScreenX11 *screen_x11;
371 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
372 screen_x11 = GDK_SCREEN_X11 (screen);
374 if (screen_x11->system_colormap)
375 return screen_x11->system_colormap;
377 colormap = g_object_new (gdk_colormap_get_type (), NULL);
378 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
380 private->screen = screen;
381 colormap->visual = gdk_screen_get_system_visual (screen);
383 private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
384 private->private_val = FALSE;
386 private->hash = NULL;
387 private->last_sync_time = 0;
388 private->info = NULL;
390 colormap->colors = NULL;
391 colormap->size = colormap->visual->colormap_size;
393 switch (colormap->visual->type)
395 case GDK_VISUAL_GRAYSCALE:
396 case GDK_VISUAL_PSEUDO_COLOR:
397 private->info = g_new0 (GdkColorInfo, colormap->size);
398 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
399 (GEqualFunc) gdk_color_equal);
401 case GDK_VISUAL_STATIC_GRAY:
402 case GDK_VISUAL_STATIC_COLOR:
403 case GDK_VISUAL_DIRECT_COLOR:
404 colormap->colors = g_new (GdkColor, colormap->size);
405 gdk_colormap_sync (colormap, TRUE);
407 case GDK_VISUAL_TRUE_COLOR:
411 gdk_colormap_add (colormap);
412 screen_x11->system_colormap = colormap;
418 gdk_colormap_get_system_size (void)
420 return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
421 GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
425 gdk_colormap_change (GdkColormap *colormap,
428 GdkColormapPrivateX11 *private;
437 g_return_if_fail (GDK_IS_COLORMAP (colormap));
439 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
441 if (private->screen->closed)
444 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
445 palette = g_new (XColor, ncolors);
447 switch (colormap->visual->type)
449 case GDK_VISUAL_GRAYSCALE:
450 case GDK_VISUAL_PSEUDO_COLOR:
451 for (i = 0; i < ncolors; i++)
453 palette[i].pixel = colormap->colors[i].pixel;
454 palette[i].red = colormap->colors[i].red;
455 palette[i].green = colormap->colors[i].green;
456 palette[i].blue = colormap->colors[i].blue;
457 palette[i].flags = DoRed | DoGreen | DoBlue;
460 XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
463 case GDK_VISUAL_DIRECT_COLOR:
464 visual = colormap->visual;
466 shift = visual->red_shift;
467 max_colors = 1 << visual->red_prec;
468 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
470 for (i = 0; i < size; i++)
472 palette[i].pixel = i << shift;
473 palette[i].red = colormap->colors[i].red;
474 palette[i].flags = DoRed;
477 XStoreColors (xdisplay, private->xcolormap, palette, size);
479 shift = visual->green_shift;
480 max_colors = 1 << visual->green_prec;
481 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
483 for (i = 0; i < size; i++)
485 palette[i].pixel = i << shift;
486 palette[i].green = colormap->colors[i].green;
487 palette[i].flags = DoGreen;
490 XStoreColors (xdisplay, private->xcolormap, palette, size);
492 shift = visual->blue_shift;
493 max_colors = 1 << visual->blue_prec;
494 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
496 for (i = 0; i < size; i++)
498 palette[i].pixel = i << shift;
499 palette[i].blue = colormap->colors[i].blue;
500 palette[i].flags = DoBlue;
503 XStoreColors (xdisplay, private->xcolormap, palette, size);
514 gdk_colors_alloc (GdkColormap *colormap,
521 GdkColormapPrivateX11 *private;
525 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
527 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
529 if (private->screen->closed)
532 return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
533 private->xcolormap,contiguous, planes,
534 nplanes, pixels, npixels);
537 for (i=0; i<npixels; i++)
539 private->info[pixels[i]].ref_count++;
540 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
544 return return_val != 0;
547 /* This is almost identical to gdk_colormap_free_colors.
551 gdk_colors_free (GdkColormap *colormap,
556 GdkColormapPrivateX11 *private;
561 g_return_if_fail (GDK_IS_COLORMAP (colormap));
562 g_return_if_fail (in_pixels != NULL);
564 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
566 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
567 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
570 pixels = g_new (gulong, in_npixels);
572 for (i=0; i<in_npixels; i++)
574 gulong pixel = in_pixels[i];
576 if (private->info[pixel].ref_count)
578 private->info[pixel].ref_count--;
580 if (private->info[pixel].ref_count == 0)
582 pixels[npixels++] = pixel;
583 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
584 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
585 private->info[pixel].flags = 0;
590 if (npixels && !private->screen->closed)
591 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
592 pixels, npixels, planes);
596 /* This is almost identical to gdk_colors_free.
600 gdk_colormap_free_colors (GdkColormap *colormap,
604 GdkColormapPrivateX11 *private;
609 g_return_if_fail (GDK_IS_COLORMAP (colormap));
610 g_return_if_fail (colors != NULL);
612 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
614 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
615 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
618 pixels = g_new (gulong, ncolors);
620 for (i=0; i<ncolors; i++)
622 gulong pixel = colors[i].pixel;
624 if (private->info[pixel].ref_count)
626 private->info[pixel].ref_count--;
628 if (private->info[pixel].ref_count == 0)
630 pixels[npixels++] = pixel;
631 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
632 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
633 private->info[pixel].flags = 0;
638 if (npixels && !private->screen->closed)
639 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
645 /********************
647 ********************/
649 /* Try to allocate a single color using XAllocColor. If it succeeds,
650 * cache the result in our colormap, and store in ret.
653 gdk_colormap_alloc1 (GdkColormap *colormap,
657 GdkColormapPrivateX11 *private;
660 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
662 xcolor.red = color->red;
663 xcolor.green = color->green;
664 xcolor.blue = color->blue;
665 xcolor.pixel = color->pixel;
666 xcolor.flags = DoRed | DoGreen | DoBlue;
668 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
670 ret->pixel = xcolor.pixel;
671 ret->red = xcolor.red;
672 ret->green = xcolor.green;
673 ret->blue = xcolor.blue;
675 if (ret->pixel < colormap->size)
677 if (private->info[ret->pixel].ref_count) /* got a duplicate */
679 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
680 &xcolor.pixel, 1, 0);
684 colormap->colors[ret->pixel] = *color;
685 colormap->colors[ret->pixel].pixel = ret->pixel;
686 private->info[ret->pixel].ref_count = 1;
688 g_hash_table_insert (private->hash,
689 &colormap->colors[ret->pixel],
690 &colormap->colors[ret->pixel]);
702 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
709 GdkColormapPrivateX11 *private;
714 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
716 if (private->private_val)
719 for (i=0; i<ncolors; i++)
721 while ((index < colormap->size) && (private->info[index].ref_count != 0))
724 if (index < colormap->size)
726 colors[i].pixel = index;
728 private->info[index].ref_count++;
729 private->info[i].flags |= GDK_COLOR_WRITEABLE;
738 pixels = g_new (gulong, ncolors);
739 /* Allocation of a writeable color cells */
741 status = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
742 FALSE, NULL, 0, pixels, ncolors);
745 for (i=0; i<ncolors; i++)
747 colors[i].pixel = pixels[i];
748 private->info[pixels[i]].ref_count++;
749 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
755 return status ? ncolors : 0;
760 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
767 GdkColormapPrivateX11 *private;
769 XColor *store = g_new (XColor, ncolors);
773 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
776 /* First, store the colors we have room for */
779 for (i=0; i<ncolors; i++)
783 while ((index < colormap->size) && (private->info[index].ref_count != 0))
786 if (index < colormap->size)
788 store[nstore].red = colors[i].red;
789 store[nstore].blue = colors[i].blue;
790 store[nstore].green = colors[i].green;
791 store[nstore].pixel = index;
796 colors[i].pixel = index;
797 private->info[index].ref_count++;
804 XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
808 if (nremaining > 0 && best_match)
810 /* Get best matches for remaining colors */
812 gchar *available = g_new (gchar, colormap->size);
813 for (i = 0; i < colormap->size; i++)
816 for (i=0; i<ncolors; i++)
820 index = gdk_colormap_match_color (colormap,
825 colors[i] = colormap->colors[index];
826 private->info[index].ref_count++;
836 return (ncolors - nremaining);
840 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
847 GdkColormapPrivateX11 *private;
852 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
855 for (i=0; i<ncolors; i++)
859 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
867 if (nremaining > 0 && best_match)
869 gchar *available = g_new (gchar, colormap->size);
870 for (i = 0; i < colormap->size; i++)
871 available[i] = ((private->info[i].ref_count == 0) ||
872 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
873 gdk_colormap_sync (colormap, FALSE);
875 while (nremaining > 0)
877 for (i=0; i<ncolors; i++)
881 index = gdk_colormap_match_color (colormap, &colors[i], available);
884 if (private->info[index].ref_count)
886 private->info[index].ref_count++;
887 colors[i] = colormap->colors[index];
893 if (gdk_colormap_alloc1 (colormap,
894 &colormap->colors[index],
903 available[index] = FALSE;
911 success[i] = 2; /* flag as permanent failure */
919 /* Change back the values we flagged as permanent failures */
922 for (i=0; i<ncolors; i++)
925 nremaining = nfailed;
928 return (ncolors - nremaining);
932 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
939 GdkColormapPrivateX11 *private;
940 GdkColor *lookup_color;
944 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
946 /* Check for an exact match among previously allocated colors */
948 for (i=0; i<ncolors; i++)
952 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
955 private->info[lookup_color->pixel].ref_count++;
956 colors[i].pixel = lookup_color->pixel;
964 /* If that failed, we try to allocate a new color, or approxmiate
965 * with what we can get if best_match is TRUE.
969 if (private->private_val)
970 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
972 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
979 gdk_colormap_alloc_colors (GdkColormap *colormap,
986 GdkColormapPrivateX11 *private;
992 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
993 g_return_val_if_fail (colors != NULL, ncolors);
995 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
997 if (private->screen->closed)
1000 for (i=0; i<ncolors; i++)
1005 switch (colormap->visual->type)
1007 case GDK_VISUAL_PSEUDO_COLOR:
1008 case GDK_VISUAL_GRAYSCALE:
1010 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1011 writeable, best_match, success);
1013 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1014 writeable, best_match, success);
1017 case GDK_VISUAL_DIRECT_COLOR:
1018 case GDK_VISUAL_TRUE_COLOR:
1019 visual = colormap->visual;
1021 for (i=0; i<ncolors; i++)
1023 colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1024 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1025 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1029 case GDK_VISUAL_STATIC_GRAY:
1030 case GDK_VISUAL_STATIC_COLOR:
1031 for (i=0; i<ncolors; i++)
1033 xcolor.red = colors[i].red;
1034 xcolor.green = colors[i].green;
1035 xcolor.blue = colors[i].blue;
1036 xcolor.pixel = colors[i].pixel;
1037 xcolor.flags = DoRed | DoGreen | DoBlue;
1039 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1041 colors[i].pixel = xcolor.pixel;
1053 * gdk_colormap_query_color:
1054 * @colormap: a #GdkColormap
1055 * @pixel: pixel value in hardware display format
1056 * @result: #GdkColor with red, green, blue fields initialized
1058 * Locates the RGB color in @colormap corresponding to the given
1059 * hardware pixel @pixel. @pixel must be a valid pixel in the
1060 * colormap; it's a programmer error to call this function with a
1061 * pixel which is not in the colormap. Hardware pixels are normally
1062 * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1063 * #GdkImage contains image data in hardware format, a #GdkPixbuf
1064 * contains image data in a canonical 24-bit RGB format.)
1066 * This function is rarely useful; it's used for example to
1067 * implement the eyedropper feature in #GtkColorSelection.
1071 gdk_colormap_query_color (GdkColormap *colormap,
1077 GdkColormapPrivateX11 *private;
1079 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1081 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1083 visual = gdk_colormap_get_visual (colormap);
1085 switch (visual->type) {
1086 case GDK_VISUAL_DIRECT_COLOR:
1087 case GDK_VISUAL_TRUE_COLOR:
1088 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1089 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1090 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1092 case GDK_VISUAL_STATIC_GRAY:
1093 case GDK_VISUAL_GRAYSCALE:
1094 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1096 case GDK_VISUAL_STATIC_COLOR:
1097 xcolor.pixel = pixel;
1098 if (!private->screen->closed)
1100 XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1101 result->red = xcolor.red;
1102 result->green = xcolor.green;
1103 result->blue = xcolor.blue;
1106 result->red = result->green = result->blue = 0;
1108 case GDK_VISUAL_PSEUDO_COLOR:
1109 g_return_if_fail (pixel < colormap->size);
1110 result->red = colormap->colors[pixel].red;
1111 result->green = colormap->colors[pixel].green;
1112 result->blue = colormap->colors[pixel].blue;
1115 g_assert_not_reached ();
1121 gdk_color_change (GdkColormap *colormap,
1124 GdkColormapPrivateX11 *private;
1127 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1128 g_return_val_if_fail (color != NULL, FALSE);
1130 xcolor.pixel = color->pixel;
1131 xcolor.red = color->red;
1132 xcolor.green = color->green;
1133 xcolor.blue = color->blue;
1134 xcolor.flags = DoRed | DoGreen | DoBlue;
1136 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1137 if (!private->screen->closed)
1138 XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1143 /* XXX: Do not use this function until it is fixed. An X Colormap
1144 * is useless unless we also have the visual.
1147 gdkx_colormap_get (Colormap xcolormap)
1149 GdkColormap *colormap;
1151 GdkColormapPrivateX11 *private;
1153 colormap = gdk_colormap_lookup (xcolormap);
1157 if (xcolormap == DefaultColormap (gdk_display, _gdk_screen))
1158 return gdk_colormap_get_system ();
1160 colormap = g_object_new (gdk_colormap_get_type (), NULL);
1161 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1163 private->xdisplay = gdk_display;
1164 private->xcolormap = xcolormap;
1165 colormap->visual = NULL;
1166 private->private_val = TRUE;
1169 /* To do the following safely, we would have to have some way of finding
1170 * out what the size or visual of the given colormap is. It seems
1171 * X doesn't allow this
1175 for (i = 0; i < 256; i++)
1177 xpalette[i].pixel = i;
1178 xpalette[i].red = 0;
1179 xpalette[i].green = 0;
1180 xpalette[i].blue = 0;
1183 XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
1185 for (i = 0; i < 256; i++)
1187 colormap->colors[i].pixel = xpalette[i].pixel;
1188 colormap->colors[i].red = xpalette[i].red;
1189 colormap->colors[i].green = xpalette[i].green;
1190 colormap->colors[i].blue = xpalette[i].blue;
1194 colormap->colors = NULL;
1197 gdk_colormap_add (colormap);
1204 gdk_colormap_match_color (GdkColormap *cmap,
1206 const gchar *available)
1210 gint rdiff, gdiff, bdiff;
1213 g_return_val_if_fail (cmap != NULL, 0);
1214 g_return_val_if_fail (color != NULL, 0);
1216 colors = cmap->colors;
1220 for (i = 0; i < cmap->size; i++)
1222 if ((!available) || (available && available[i]))
1224 rdiff = (color->red - colors[i].red);
1225 gdiff = (color->green - colors[i].green);
1226 bdiff = (color->blue - colors[i].blue);
1228 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1243 gdk_colormap_lookup (Colormap xcolormap)
1250 cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
1255 gdk_colormap_add (GdkColormap *cmap)
1257 GdkColormapPrivateX11 *private;
1260 colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1261 (GEqualFunc) gdk_colormap_equal);
1263 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1265 g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
1269 gdk_colormap_remove (GdkColormap *cmap)
1271 GdkColormapPrivateX11 *private;
1273 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1275 g_hash_table_remove (colormap_hash, &private->xcolormap);
1279 gdk_colormap_hash (Colormap *cmap)
1285 gdk_colormap_equal (Colormap *a,
1292 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1294 GdkColormapPrivateX11 *private;
1296 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1298 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1300 return private->xdisplay;
1304 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1306 GdkColormapPrivateX11 *private;
1308 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1310 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1312 if (private->screen->closed)
1315 return private->xcolormap;
1319 * gdk_colormap_get_screen:
1320 * @cmap: a #GdkColormap
1322 * Gets the screen for which this colormap was created.
1324 * Return value: the screen for which this colormap was created.
1327 gdk_colormap_get_screen (GdkColormap *cmap)
1329 g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1331 return GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;