1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Color.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
4 // Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
35 #include "BaseDisplay.hh"
38 BColor::ColorCache BColor::colorcache;
39 bool BColor::cleancache = false;
41 BColor::BColor(const BaseDisplay * const _display, unsigned int _screen)
42 : allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen)
45 BColor::BColor(int _r, int _g, int _b,
46 const BaseDisplay * const _display, unsigned int _screen)
47 : allocated(false), r(_r), g(_g), b(_b), p(0), dpy(_display), scrn(_screen)
51 BColor::BColor(const std::string &_name,
52 const BaseDisplay * const _display, unsigned int _screen)
53 : allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen),
59 BColor::~BColor(void) {
64 void BColor::setDisplay(const BaseDisplay * const _display,
65 unsigned int _screen) {
66 if (_display == display() && _screen == screen()) {
76 if (! colorname.empty()) {
82 unsigned long BColor::pixel(void) const {
85 BColor *that = (BColor *) this;
93 void BColor::parseColorName(void) {
96 if (colorname.empty()) {
97 fprintf(stderr, "BColor: empty colorname, cannot parse (using black)\n");
102 scrn = DefaultScreen(display()->getXDisplay());
103 Colormap colormap = display()->getScreenInfo(scrn)->getColormap();
105 // get rgb values from colorname
112 if (! XParseColor(display()->getXDisplay(), colormap,
113 colorname.c_str(), &xcol)) {
114 fprintf(stderr, "BColor::allocate: color parse error: \"%s\"\n",
120 setRGB(xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8);
124 void BColor::allocate(void) {
127 if (scrn == ~(0u)) scrn = DefaultScreen(display()->getXDisplay());
128 Colormap colormap = display()->getScreenInfo(scrn)->getColormap();
131 if (colorname.empty()) {
132 fprintf(stderr, "BColor: cannot allocate invalid color (using black)\n");
139 // see if we have allocated this color before
140 RGB rgb(display(), scrn, r, g, b);
141 ColorCache::iterator it = colorcache.find(rgb);
142 if (it != colorcache.end()) {
146 (*it).second.count++;
150 // allocate color from rgb values
152 xcol.red = r | r << 8;
153 xcol.green = g | g << 8;
154 xcol.blue = b | b << 8;
157 if (! XAllocColor(display()->getXDisplay(), colormap, &xcol)) {
158 fprintf(stderr, "BColor::allocate: color alloc error: rgb:%x/%x/%x\n",
166 colorcache.insert(ColorCacheItem(rgb, PixelRef(p)));
173 void BColor::deallocate(void) {
179 ColorCache::iterator it = colorcache.find(RGB(display(), scrn, r, g, b));
180 if (it != colorcache.end()) {
181 if ((*it).second.count >= 1)
182 (*it).second.count--;
192 BColor &BColor::operator=(const BColor &c) {
195 setRGB(c.r, c.g, c.b);
196 colorname = c.colorname;
203 void BColor::cleanupColorCache(void) {
208 void BColor::doCacheCleanup(void) {
209 // ### TODO - support multiple displays!
210 ColorCache::iterator it = colorcache.begin();
211 if (it == colorcache.end()) {
216 const BaseDisplay* const display = (*it).first.display;
217 unsigned long *pixels = new unsigned long[ colorcache.size() ];
218 unsigned int i, count;
220 for (i = 0; i < display->getNumberOfScreens(); i++) {
222 it = colorcache.begin();
224 while (it != colorcache.end()) {
225 if ((*it).second.count != 0 || (*it).first.screen != i) {
230 pixels[ count++ ] = (*it).second.p;
231 ColorCache::iterator it2 = it;
233 colorcache.erase(it2);
237 XFreeColors(display->getXDisplay(),
238 display->getScreenInfo(i)->getColormap(),