]>
Dogcows Code - chaz/openbox/blob - obrender/instance.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 instance.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
23 static RrInstance
*definst
= NULL
;
25 static void RrTrueColorSetup (RrInstance
*inst
);
26 static void RrPseudoColorSetup (RrInstance
*inst
);
37 g_error("color %d (%d,%d,%d) in hash table with %d "
38 "leftover references",
39 c
->id
, RrColorRed(c
), RrColorGreen(c
), RrColorBlue(c
),
45 static void f(gpointer key
, gpointer value
, gpointer n
)
48 if (c
->id
== *(gint
*)n
)
49 g_message("color %d has %d references", c
->id
, c
->refcount
);
52 void print_refs(gint id
)
54 g_hash_table_foreach(RrColorHash(definst
), f
, &id
);
58 RrInstance
* RrInstanceNew (Display
*display
, gint screen
)
60 definst
= g_slice_new(RrInstance
);
61 definst
->display
= display
;
62 definst
->screen
= screen
;
64 definst
->depth
= DefaultDepth(display
, screen
);
65 definst
->visual
= DefaultVisual(display
, screen
);
66 definst
->colormap
= DefaultColormap(display
, screen
);
67 definst
->pango
= pango_xft_get_context(display
, screen
);
69 definst
->pseudo_colors
= NULL
;
71 definst
->color_hash
= g_hash_table_new_full(g_int_hash
, g_int_equal
,
74 switch (definst
->visual
->class) {
76 RrTrueColorSetup(definst
);
82 RrPseudoColorSetup(definst
);
85 g_critical("Unsupported visual class");
87 return definst
= NULL
;
92 static void RrTrueColorSetup (RrInstance
*inst
)
94 gulong red_mask
, green_mask
, blue_mask
;
95 XImage
*timage
= NULL
;
97 timage
= XCreateImage(inst
->display
, inst
->visual
, inst
->depth
,
98 ZPixmap
, 0, NULL
, 1, 1, 32, 0);
99 g_assert(timage
!= NULL
);
100 /* find the offsets for each color in the visual's masks */
101 inst
->red_mask
= red_mask
= timage
->red_mask
;
102 inst
->green_mask
= green_mask
= timage
->green_mask
;
103 inst
->blue_mask
= blue_mask
= timage
->blue_mask
;
105 inst
->red_offset
= 0;
106 inst
->green_offset
= 0;
107 inst
->blue_offset
= 0;
109 while (! (red_mask
& 1)) { inst
->red_offset
++; red_mask
>>= 1; }
110 while (! (green_mask
& 1)) { inst
->green_offset
++; green_mask
>>= 1; }
111 while (! (blue_mask
& 1)) { inst
->blue_offset
++; blue_mask
>>= 1; }
113 inst
->red_shift
= inst
->green_shift
= inst
->blue_shift
= 8;
114 while (red_mask
) { red_mask
>>= 1; inst
->red_shift
--; }
115 while (green_mask
) { green_mask
>>= 1; inst
->green_shift
--; }
116 while (blue_mask
) { blue_mask
>>= 1; inst
->blue_shift
--; }
120 #define RrPseudoNcolors(inst) (1 << (inst->pseudo_bpc * 3))
122 static void RrPseudoColorSetup (RrInstance
*inst
)
125 gint tr
, tg
, tb
, n
, r
, g
, b
, i
, incolors
, ii
;
129 /* determine the number of colors and the bits-per-color */
130 inst
->pseudo_bpc
= 2; /* XXX THIS SHOULD BE A USER OPTION */
131 g_assert(inst
->pseudo_bpc
>= 1);
132 _ncolors
= RrPseudoNcolors(inst
);
134 if (_ncolors
> 1 << inst
->depth
) {
135 g_message("Invalid colormap size. Resizing.");
136 inst
->pseudo_bpc
= 1 << (inst
->depth
/3) >> 3;
137 _ncolors
= 1 << (inst
->pseudo_bpc
* 3);
140 /* build a color cube */
141 inst
->pseudo_colors
= g_new(XColor
, _ncolors
);
142 cpc
= 1 << inst
->pseudo_bpc
; /* colors per channel */
144 for (n
= 0, r
= 0; r
< cpc
; r
++)
145 for (g
= 0; g
< cpc
; g
++)
146 for (b
= 0; b
< cpc
; b
++, n
++) {
147 tr
= (gint
)(((gfloat
)(r
)/(gfloat
)(cpc
-1)) * 0xFF);
148 tg
= (gint
)(((gfloat
)(g
)/(gfloat
)(cpc
-1)) * 0xFF);
149 tb
= (gint
)(((gfloat
)(b
)/(gfloat
)(cpc
-1)) * 0xFF);
150 inst
->pseudo_colors
[n
].red
= tr
| tr
<< 8;
151 inst
->pseudo_colors
[n
].green
= tg
| tg
<< 8;
152 inst
->pseudo_colors
[n
].blue
= tb
| tb
<< 8;
153 /* used to track allocation */
154 inst
->pseudo_colors
[n
].flags
= DoRed
|DoGreen
|DoBlue
;
157 /* allocate the colors */
158 for (i
= 0; i
< _ncolors
; i
++)
159 if (!XAllocColor(inst
->display
, inst
->colormap
,
160 &inst
->pseudo_colors
[i
]))
161 inst
->pseudo_colors
[i
].flags
= 0; /* mark it as unallocated */
163 /* try allocate any colors that failed allocation above */
165 /* get the allocated values from the X server
166 (only the first 256 XXX why!?)
168 incolors
= (((1 << inst
->depth
) > 256) ? 256 : (1 << inst
->depth
));
169 for (i
= 0; i
< incolors
; i
++)
170 icolors
[i
].pixel
= i
;
171 XQueryColors(inst
->display
, inst
->colormap
, icolors
, incolors
);
173 /* try match unallocated ones */
174 for (i
= 0; i
< _ncolors
; i
++) {
175 if (!inst
->pseudo_colors
[i
].flags
) { /* if it wasn't allocated... */
176 gulong closest
= 0xffffffff, close
= 0;
177 for (ii
= 0; ii
< incolors
; ii
++) {
178 /* find deviations */
179 r
= (inst
->pseudo_colors
[i
].red
- icolors
[ii
].red
) & 0xff;
180 g
= (inst
->pseudo_colors
[i
].green
- icolors
[ii
].green
) & 0xff;
181 b
= (inst
->pseudo_colors
[i
].blue
- icolors
[ii
].blue
) & 0xff;
182 /* find a weighted absolute deviation */
183 dev
= (r
* r
) + (g
* g
) + (b
* b
);
191 inst
->pseudo_colors
[i
].red
= icolors
[close
].red
;
192 inst
->pseudo_colors
[i
].green
= icolors
[close
].green
;
193 inst
->pseudo_colors
[i
].blue
= icolors
[close
].blue
;
194 inst
->pseudo_colors
[i
].pixel
= icolors
[close
].pixel
;
196 /* try alloc this closest color, it had better succeed! */
197 if (XAllocColor(inst
->display
, inst
->colormap
,
198 &inst
->pseudo_colors
[i
]))
199 /* mark as alloced */
200 inst
->pseudo_colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
202 /* wtf has gone wrong, its already alloced for chissake! */
203 g_assert_not_reached();
208 void RrInstanceFree (RrInstance
*inst
)
211 if (inst
== definst
) definst
= NULL
;
212 g_free(inst
->pseudo_colors
);
213 g_hash_table_destroy(inst
->color_hash
);
214 g_object_unref(inst
->pango
);
215 g_slice_free(RrInstance
, inst
);
219 Display
* RrDisplay (const RrInstance
*inst
)
221 return (inst
? inst
: definst
)->display
;
224 gint
RrScreen (const RrInstance
*inst
)
226 return (inst
? inst
: definst
)->screen
;
229 Window
RrRootWindow (const RrInstance
*inst
)
231 return RootWindow (RrDisplay (inst
), RrScreen (inst
));
234 Visual
*RrVisual (const RrInstance
*inst
)
236 return (inst
? inst
: definst
)->visual
;
239 gint
RrDepth (const RrInstance
*inst
)
241 return (inst
? inst
: definst
)->depth
;
244 Colormap
RrColormap (const RrInstance
*inst
)
246 return (inst
? inst
: definst
)->colormap
;
249 gint
RrRedOffset (const RrInstance
*inst
)
251 return (inst
? inst
: definst
)->red_offset
;
254 gint
RrGreenOffset (const RrInstance
*inst
)
256 return (inst
? inst
: definst
)->green_offset
;
259 gint
RrBlueOffset (const RrInstance
*inst
)
261 return (inst
? inst
: definst
)->blue_offset
;
264 gint
RrRedShift (const RrInstance
*inst
)
266 return (inst
? inst
: definst
)->red_shift
;
269 gint
RrGreenShift (const RrInstance
*inst
)
271 return (inst
? inst
: definst
)->green_shift
;
274 gint
RrBlueShift (const RrInstance
*inst
)
276 return (inst
? inst
: definst
)->blue_shift
;
279 gint
RrRedMask (const RrInstance
*inst
)
281 return (inst
? inst
: definst
)->red_mask
;
284 gint
RrGreenMask (const RrInstance
*inst
)
286 return (inst
? inst
: definst
)->green_mask
;
289 gint
RrBlueMask (const RrInstance
*inst
)
291 return (inst
? inst
: definst
)->blue_mask
;
294 guint
RrPseudoBPC (const RrInstance
*inst
)
296 return (inst
? inst
: definst
)->pseudo_bpc
;
299 XColor
*RrPseudoColors (const RrInstance
*inst
)
301 return (inst
? inst
: definst
)->pseudo_colors
;
304 GHashTable
* RrColorHash (const RrInstance
*inst
)
306 return (inst
? inst
: definst
)->color_hash
;
This page took 0.053195 seconds and 5 git commands to generate.