]> Dogcows Code - chaz/openbox/blob - render/theme.c
add a menuOverlap property to themes, and use it in the submenu placement
[chaz/openbox] / render / theme.c
1 #include "render.h"
2 #include "color.h"
3 #include "font.h"
4 #include "mask.h"
5 #include "theme.h"
6
7 #include <X11/Xlib.h>
8 #include <X11/Xresource.h>
9
10 static XrmDatabase loaddb(RrTheme *theme, char *name);
11 static gboolean read_int(XrmDatabase db, char *rname, int *value);
12 static gboolean read_string(XrmDatabase db, char *rname, char **value);
13 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
14 gchar *rname, RrColor **value);
15 static gboolean read_mask(const RrInstance *inst,
16 gchar *maskname, RrTheme *theme,
17 RrPixmapMask **value);
18 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
19 gchar *rname, RrAppearance *value);
20 static void set_default_appearance(RrAppearance *a);
21
22 RrTheme* RrThemeNew(const RrInstance *inst, gchar *name)
23 {
24 XrmDatabase db = NULL;
25 RrJustify winjust, mtitlejust, mjust;
26 gchar *str;
27 gchar *font_str;
28 RrTheme *theme;
29
30 theme = g_new0(RrTheme, 1);
31
32 theme->inst = inst;
33
34 theme->a_disabled_focused_max = RrAppearanceNew(inst, 1);
35 theme->a_disabled_unfocused_max = RrAppearanceNew(inst, 1);
36 theme->a_focused_unpressed_max = RrAppearanceNew(inst, 1);
37 theme->a_focused_pressed_max = RrAppearanceNew(inst, 1);
38 theme->a_focused_pressed_set_max = RrAppearanceNew(inst, 1);
39 theme->a_unfocused_unpressed_max = RrAppearanceNew(inst, 1);
40 theme->a_unfocused_pressed_max = RrAppearanceNew(inst, 1);
41 theme->a_unfocused_pressed_set_max = RrAppearanceNew(inst, 1);
42 theme->a_focused_grip = RrAppearanceNew(inst, 0);
43 theme->a_unfocused_grip = RrAppearanceNew(inst, 0);
44 theme->a_focused_title = RrAppearanceNew(inst, 0);
45 theme->a_unfocused_title = RrAppearanceNew(inst, 0);
46 theme->a_focused_label = RrAppearanceNew(inst, 1);
47 theme->a_unfocused_label = RrAppearanceNew(inst, 1);
48 theme->a_icon = RrAppearanceNew(inst, 1);
49 theme->a_focused_handle = RrAppearanceNew(inst, 0);
50 theme->a_unfocused_handle = RrAppearanceNew(inst, 0);
51 theme->a_menu = RrAppearanceNew(inst, 0);
52 theme->a_menu_title = RrAppearanceNew(inst, 1);
53 theme->a_menu_item = RrAppearanceNew(inst, 1);
54 theme->a_menu_disabled = RrAppearanceNew(inst, 1);
55 theme->a_menu_hilite = RrAppearanceNew(inst, 1);
56
57 theme->app_hilite_bg = RrAppearanceNew(inst, 0);
58 theme->app_unhilite_bg = RrAppearanceNew(inst, 0);
59 theme->app_hilite_label = RrAppearanceNew(inst, 1);
60 theme->app_unhilite_label = RrAppearanceNew(inst, 1);
61 theme->app_icon = RrAppearanceNew(inst, 1);
62
63 if (name) {
64 db = loaddb(theme, name);
65 if (db == NULL) {
66 g_warning("Failed to load the theme '%s'", name);
67 g_message("Falling back to the default: '%s'", DEFAULT_THEME);
68 } else
69 theme->name = g_path_get_basename(name);
70 }
71 if (db == NULL) {
72 db = loaddb(theme, DEFAULT_THEME);
73 if (db == NULL) {
74 g_warning("Failed to load the theme '%s'.", DEFAULT_THEME);
75 return NULL;
76 } else
77 theme->name = g_path_get_basename(DEFAULT_THEME);
78 }
79
80 /* load the font stuff */
81 if (!read_string(db, "window.title.xftfont", &font_str))
82 font_str = "arial,sans:bold:pixelsize=10:shadow=y:shadowtint=50";
83
84 if (!(theme->winfont = RrFontOpen(inst, font_str))) {
85 RrThemeFree(theme);
86 return NULL;
87 }
88 theme->winfont_height = RrFontHeight(theme->winfont);
89
90 winjust = RR_JUSTIFY_LEFT;
91 if (read_string(db, "window.justify", &str)) {
92 if (!g_ascii_strcasecmp(str, "right"))
93 winjust = RR_JUSTIFY_RIGHT;
94 else if (!g_ascii_strcasecmp(str, "center"))
95 winjust = RR_JUSTIFY_CENTER;
96 }
97
98 if (!read_string(db, "menu.title.xftfont", &font_str))
99 font_str = "arial,sans:bold:pixelsize=12:shadow=y";
100
101 if (!(theme->mtitlefont = RrFontOpen(inst, font_str))) {
102 RrThemeFree(theme);
103 return NULL;
104 }
105 theme->mtitlefont_height = RrFontHeight(theme->mtitlefont);
106
107 mtitlejust = RR_JUSTIFY_LEFT;
108 if (read_string(db, "menu.title.justify", &str)) {
109 if (!g_ascii_strcasecmp(str, "right"))
110 mtitlejust = RR_JUSTIFY_RIGHT;
111 else if (!g_ascii_strcasecmp(str, "center"))
112 mtitlejust = RR_JUSTIFY_CENTER;
113 }
114
115 if (!read_string(db, "menu.frame.xftfont", &font_str))
116 font_str = "arial,sans:bold:pixelsize=11:shadow=y";
117
118 if (!(theme->mfont = RrFontOpen(inst, font_str))) {
119 RrThemeFree(theme);
120 return NULL;
121 }
122 theme->mfont_height = RrFontHeight(theme->mfont);
123
124 mjust = RR_JUSTIFY_LEFT;
125 if (read_string(db, "menu.frame.justify", &str)) {
126 if (!g_ascii_strcasecmp(str, "right"))
127 mjust = RR_JUSTIFY_RIGHT;
128 else if (!g_ascii_strcasecmp(str, "center"))
129 mjust = RR_JUSTIFY_CENTER;
130 }
131
132 /* load the title layout */
133 if (!read_string(db, "window.title.layout", &font_str))
134 font_str = "NLIMC";
135 theme->title_layout = g_strdup(font_str);
136
137 /* load direct dimensions */
138 if (!read_int(db, "menuOverlap", &theme->menu_overlap) ||
139 theme->menu_overlap < 0 || theme->menu_overlap > 20)
140 theme->handle_height = 0;
141 if (!read_int(db, "handleWidth", &theme->handle_height) ||
142 theme->handle_height < 0 || theme->handle_height > 100)
143 theme->handle_height = 6;
144 if (!read_int(db, "bevelWidth", &theme->bevel) ||
145 theme->bevel <= 0 || theme->bevel > 100) theme->bevel = 3;
146 if (!read_int(db, "borderWidth", &theme->bwidth) ||
147 theme->bwidth < 0 || theme->bwidth > 100) theme->bwidth = 1;
148 if (!read_int(db, "frameWidth", &theme->cbwidth) ||
149 theme->cbwidth < 0 || theme->cbwidth > 100)
150 theme->cbwidth = theme->bevel;
151
152 /* load colors */
153 if (!read_color(db, inst,
154 "borderColor", &theme->b_color))
155 theme->b_color = RrColorNew(inst, 0, 0, 0);
156 if (!read_color(db, inst,
157 "window.frame.focusColor", &theme->cb_focused_color))
158 theme->cb_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
159 if (!read_color(db, inst,
160 "window.frame.unfocusColor",&theme->cb_unfocused_color))
161 theme->cb_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
162 if (!read_color(db, inst,
163 "window.label.focus.textColor",
164 &theme->title_focused_color))
165 theme->title_focused_color = RrColorNew(inst, 0x0, 0x0, 0x0);
166 if (!read_color(db, inst,
167 "window.label.unfocus.textColor",
168 &theme->title_unfocused_color))
169 theme->title_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
170 if (!read_color(db, inst,
171 "window.button.focus.picColor",
172 &theme->titlebut_focused_color))
173 theme->titlebut_focused_color = RrColorNew(inst, 0, 0, 0);
174 if (!read_color(db, inst,
175 "window.button.unfocus.picColor",
176 &theme->titlebut_unfocused_color))
177 theme->titlebut_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
178 if (!read_color(db, inst,
179 "window.button.disabled.focus.picColor",
180 &theme->titlebut_disabled_focused_color))
181 theme->titlebut_disabled_focused_color =
182 RrColorNew(inst, 0xff, 0xff, 0xff);
183 if (!read_color(db, inst,
184 "window.button.disabled.unfocus.picColor",
185 &theme->titlebut_disabled_unfocused_color))
186 theme->titlebut_disabled_unfocused_color = RrColorNew(inst, 0, 0, 0);
187 if (!read_color(db, inst,
188 "menu.title.textColor", &theme->menu_title_color))
189 theme->menu_title_color = RrColorNew(inst, 0, 0, 0);
190 if (!read_color(db, inst,
191 "menu.frame.textColor", &theme->menu_color))
192 theme->menu_color = RrColorNew(inst, 0xff, 0xff, 0xff);
193 if (!read_color(db, inst,
194 "menu.frame.disableColor", &theme->menu_disabled_color))
195 theme->menu_disabled_color = RrColorNew(inst, 0, 0, 0);
196 if (!read_color(db, inst,
197 "menu.hilite.textColor", &theme->menu_hilite_color))
198 theme->menu_hilite_color = RrColorNew(inst, 0, 0, 0);
199
200 if (read_mask(inst, "max.xbm", theme, &theme->max_unset_mask)){
201 if (!read_mask(inst, "max_t.xbm", theme, &theme->max_set_mask)) {
202 theme->max_set_mask = RrPixmapMaskCopy(theme->max_unset_mask);
203 }
204 } else {
205 {
206 char data[] = { 0x7f, 0x7f, 0x7f, 0x41, 0x41, 0x41, 0x7f };
207 theme->max_unset_mask = RrPixmapMaskNew(inst, 7, 7, data);
208 }
209 {
210 char data[] = { 0x7c, 0x44, 0x47, 0x47, 0x7f, 0x1f, 0x1f };
211 theme->max_set_mask = RrPixmapMaskNew(inst, 7, 7, data);
212 }
213 }
214
215 if (!read_mask(inst, "iconify.xbm", theme, &theme->iconify_mask)) {
216 char data[] = { 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f };
217 theme->iconify_mask = RrPixmapMaskNew(inst, 7, 7, data);
218 }
219
220 if (read_mask(inst, "stick.xbm", theme, &theme->desk_unset_mask)) {
221 if (!read_mask(inst, "stick_t.xbm", theme, &theme->desk_set_mask)) {
222 theme->desk_set_mask =
223 RrPixmapMaskCopy(theme->desk_unset_mask);
224 }
225 } else {
226 {
227 char data[] = { 0x63, 0x63, 0x00, 0x00, 0x00, 0x63, 0x63 };
228 theme->desk_unset_mask = RrPixmapMaskNew(inst, 7, 7, data);
229 }
230 {
231 char data[] = { 0x00, 0x36, 0x36, 0x08, 0x36, 0x36, 0x00 };
232 theme->desk_set_mask = RrPixmapMaskNew(inst, 7, 7, data);
233 }
234 }
235
236 if (read_mask(inst, "shade.xbm", theme, &theme->shade_unset_mask)) {
237 if (!read_mask(inst, "shade_t.xbm", theme, &theme->shade_set_mask)) {
238 theme->shade_set_mask =
239 RrPixmapMaskCopy(theme->shade_unset_mask);
240 }
241 } else {
242 {
243 char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 };
244 theme->shade_unset_mask = RrPixmapMaskNew(inst, 7, 7, data);
245 }
246 {
247 char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x7f };
248 theme->shade_set_mask = RrPixmapMaskNew(inst, 7, 7, data);
249 }
250 }
251
252 if (!read_mask(inst, "close.xbm", theme, &theme->close_mask)) {
253 char data[] = { 0x63, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x63 };
254 theme->close_mask = RrPixmapMaskNew(inst, 7, 7, data);
255 }
256
257 /* read the decoration textures */
258 if (!read_appearance(db, inst,
259 "window.title.focus", theme->a_focused_title))
260 set_default_appearance(theme->a_focused_title);
261 if (!read_appearance(db, inst,
262 "window.title.unfocus", theme->a_unfocused_title))
263 set_default_appearance(theme->a_unfocused_title);
264 if (!read_appearance(db, inst,
265 "window.label.focus", theme->a_focused_label))
266 set_default_appearance(theme->a_focused_label);
267 if (!read_appearance(db, inst,
268 "window.label.unfocus", theme->a_unfocused_label))
269 set_default_appearance(theme->a_unfocused_label);
270 if (!read_appearance(db, inst,
271 "window.handle.focus", theme->a_focused_handle))
272 set_default_appearance(theme->a_focused_handle);
273 if (!read_appearance(db, inst,
274 "window.handle.unfocus",theme->a_unfocused_handle))
275 set_default_appearance(theme->a_unfocused_handle);
276 if (!read_appearance(db, inst,
277 "window.grip.focus", theme->a_focused_grip))
278 set_default_appearance(theme->a_focused_grip);
279 if (!read_appearance(db, inst,
280 "window.grip.unfocus", theme->a_unfocused_grip))
281 set_default_appearance(theme->a_unfocused_grip);
282 if (!read_appearance(db, inst,
283 "menu.frame", theme->a_menu))
284 set_default_appearance(theme->a_menu);
285 if (!read_appearance(db, inst,
286 "menu.title", theme->a_menu_title))
287 set_default_appearance(theme->a_menu_title);
288 if (!read_appearance(db, inst,
289 "menu.hilite", theme->a_menu_hilite))
290 set_default_appearance(theme->a_menu_hilite);
291
292 /* read the appearances for rendering non-decorations */
293 if (!read_appearance(db, inst,
294 "window.title.focus", theme->app_hilite_bg))
295 set_default_appearance(theme->app_hilite_bg);
296 if (!read_appearance(db, inst,
297 "window.label.focus", theme->app_hilite_label))
298 set_default_appearance(theme->app_hilite_label);
299 if (!read_appearance(db, inst,
300 "window.title.unfocus", theme->app_unhilite_bg))
301 set_default_appearance(theme->app_unhilite_bg);
302 if (!read_appearance(db, inst,
303 "window.label.unfocus", theme->app_unhilite_label))
304 set_default_appearance(theme->app_unhilite_label);
305
306 /* read buttons textures */
307 if (!read_appearance(db, inst,
308 "window.button.disabled.focus",
309 theme->a_disabled_focused_max))
310 set_default_appearance(theme->a_disabled_focused_max);
311 if (!read_appearance(db, inst,
312 "window.button.disabled.unfocus",
313 theme->a_disabled_unfocused_max))
314 set_default_appearance(theme->a_disabled_unfocused_max);
315 if (!read_appearance(db, inst,
316 "window.button.pressed.focus",
317 theme->a_focused_pressed_max))
318 if (!read_appearance(db, inst,
319 "window.button.pressed",
320 theme->a_focused_pressed_max))
321 set_default_appearance(theme->a_focused_pressed_max);
322 if (!read_appearance(db, inst,
323 "window.button.pressed.unfocus",
324 theme->a_unfocused_pressed_max))
325 if (!read_appearance(db, inst,
326 "window.button.pressed",
327 theme->a_unfocused_pressed_max))
328 set_default_appearance(theme->a_unfocused_pressed_max);
329 if (!read_appearance(db, inst,
330 "window.button.focus",
331 theme->a_focused_unpressed_max))
332 set_default_appearance(theme->a_focused_unpressed_max);
333 if (!read_appearance(db, inst,
334 "window.button.unfocus",
335 theme->a_unfocused_unpressed_max))
336 set_default_appearance(theme->a_unfocused_unpressed_max);
337
338 theme->a_disabled_focused_close =
339 RrAppearanceCopy(theme->a_disabled_focused_max);
340 theme->a_disabled_unfocused_close =
341 RrAppearanceCopy(theme->a_disabled_unfocused_max);
342 theme->a_unfocused_unpressed_close =
343 RrAppearanceCopy(theme->a_unfocused_unpressed_max);
344 theme->a_unfocused_pressed_close =
345 RrAppearanceCopy(theme->a_unfocused_pressed_max);
346 theme->a_focused_unpressed_close =
347 RrAppearanceCopy(theme->a_focused_unpressed_max);
348 theme->a_focused_pressed_close =
349 RrAppearanceCopy(theme->a_focused_pressed_max);
350 theme->a_disabled_focused_desk =
351 RrAppearanceCopy(theme->a_disabled_focused_max);
352 theme->a_disabled_unfocused_desk =
353 RrAppearanceCopy(theme->a_disabled_unfocused_max);
354 theme->a_unfocused_unpressed_desk =
355 RrAppearanceCopy(theme->a_unfocused_unpressed_max);
356 theme->a_unfocused_pressed_desk =
357 RrAppearanceCopy(theme->a_unfocused_pressed_max);
358 theme->a_unfocused_pressed_set_desk =
359 RrAppearanceCopy(theme->a_unfocused_pressed_max);
360 theme->a_focused_unpressed_desk =
361 RrAppearanceCopy(theme->a_focused_unpressed_max);
362 theme->a_focused_pressed_desk =
363 RrAppearanceCopy(theme->a_focused_pressed_max);
364 theme->a_focused_pressed_set_desk =
365 RrAppearanceCopy(theme->a_focused_pressed_max);
366 theme->a_disabled_focused_shade =
367 RrAppearanceCopy(theme->a_disabled_focused_max);
368 theme->a_disabled_unfocused_shade =
369 RrAppearanceCopy(theme->a_disabled_unfocused_max);
370 theme->a_unfocused_unpressed_shade =
371 RrAppearanceCopy(theme->a_unfocused_unpressed_max);
372 theme->a_unfocused_pressed_shade =
373 RrAppearanceCopy(theme->a_unfocused_pressed_max);
374 theme->a_unfocused_pressed_set_shade =
375 RrAppearanceCopy(theme->a_unfocused_pressed_max);
376 theme->a_focused_unpressed_shade =
377 RrAppearanceCopy(theme->a_focused_unpressed_max);
378 theme->a_focused_pressed_shade =
379 RrAppearanceCopy(theme->a_focused_pressed_max);
380 theme->a_focused_pressed_set_shade =
381 RrAppearanceCopy(theme->a_focused_pressed_max);
382 theme->a_disabled_focused_iconify =
383 RrAppearanceCopy(theme->a_disabled_focused_max);
384 theme->a_disabled_unfocused_iconify =
385 RrAppearanceCopy(theme->a_disabled_focused_max);
386 theme->a_unfocused_unpressed_iconify =
387 RrAppearanceCopy(theme->a_unfocused_unpressed_max);
388 theme->a_unfocused_pressed_iconify =
389 RrAppearanceCopy(theme->a_unfocused_pressed_max);
390 theme->a_focused_unpressed_iconify =
391 RrAppearanceCopy(theme->a_focused_unpressed_max);
392 theme->a_focused_pressed_iconify =
393 RrAppearanceCopy(theme->a_focused_pressed_max);
394 theme->a_unfocused_pressed_set_max =
395 RrAppearanceCopy(theme->a_unfocused_pressed_max);
396 theme->a_focused_pressed_set_max =
397 RrAppearanceCopy(theme->a_focused_pressed_max);
398
399 theme->a_icon->surface.grad = RR_SURFACE_PARENTREL;
400
401 /* set up the textures */
402 theme->a_focused_label->texture[0].type =
403 theme->app_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
404 theme->a_focused_label->texture[0].data.text.justify = winjust;
405 theme->app_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
406 theme->a_focused_label->texture[0].data.text.font =
407 theme->app_hilite_label->texture[0].data.text.font = theme->winfont;
408 theme->a_focused_label->texture[0].data.text.color =
409 theme->app_hilite_label->texture[0].data.text.color =
410 theme->title_focused_color;
411
412 theme->a_unfocused_label->texture[0].type =
413 theme->app_unhilite_label->texture[0].type = RR_TEXTURE_TEXT;
414 theme->a_unfocused_label->texture[0].data.text.justify = winjust;
415 theme->app_unhilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
416 theme->a_unfocused_label->texture[0].data.text.font =
417 theme->app_unhilite_label->texture[0].data.text.font = theme->winfont;
418 theme->a_unfocused_label->texture[0].data.text.color =
419 theme->app_unhilite_label->texture[0].data.text.color =
420 theme->title_unfocused_color;
421
422 theme->a_menu_title->texture[0].type = RR_TEXTURE_TEXT;
423 theme->a_menu_title->texture[0].data.text.justify = mtitlejust;
424 theme->a_menu_title->texture[0].data.text.font = theme->mtitlefont;
425 theme->a_menu_title->texture[0].data.text.color = theme->menu_title_color;
426
427 theme->a_menu_item->surface.grad =
428 theme->a_menu_disabled->surface.grad =
429 theme->app_icon->surface.grad = RR_SURFACE_PARENTREL;
430
431 theme->a_menu_item->texture[0].type =
432 theme->a_menu_disabled->texture[0].type =
433 theme->a_menu_hilite->texture[0].type = RR_TEXTURE_TEXT;
434 theme->a_menu_item->texture[0].data.text.justify =
435 theme->a_menu_disabled->texture[0].data.text.justify =
436 theme->a_menu_hilite->texture[0].data.text.justify = mjust;
437 theme->a_menu_item->texture[0].data.text.font =
438 theme->a_menu_disabled->texture[0].data.text.font =
439 theme->a_menu_hilite->texture[0].data.text.font = theme->mfont;
440 theme->a_menu_item->texture[0].data.text.color = theme->menu_color;
441 theme->a_menu_disabled->texture[0].data.text.color =
442 theme->menu_disabled_color;
443 theme->a_menu_hilite->texture[0].data.text.color =
444 theme->menu_hilite_color;
445
446 theme->a_disabled_focused_max->texture[0].type =
447 theme->a_disabled_unfocused_max->texture[0].type =
448 theme->a_focused_unpressed_max->texture[0].type =
449 theme->a_focused_pressed_max->texture[0].type =
450 theme->a_focused_pressed_set_max->texture[0].type =
451 theme->a_unfocused_unpressed_max->texture[0].type =
452 theme->a_unfocused_pressed_max->texture[0].type =
453 theme->a_unfocused_pressed_set_max->texture[0].type =
454 theme->a_disabled_focused_close->texture[0].type =
455 theme->a_disabled_unfocused_close->texture[0].type =
456 theme->a_focused_unpressed_close->texture[0].type =
457 theme->a_focused_pressed_close->texture[0].type =
458 theme->a_unfocused_unpressed_close->texture[0].type =
459 theme->a_unfocused_pressed_close->texture[0].type =
460 theme->a_disabled_focused_desk->texture[0].type =
461 theme->a_disabled_unfocused_desk->texture[0].type =
462 theme->a_focused_unpressed_desk->texture[0].type =
463 theme->a_focused_pressed_desk->texture[0].type =
464 theme->a_focused_pressed_set_desk->texture[0].type =
465 theme->a_unfocused_unpressed_desk->texture[0].type =
466 theme->a_unfocused_pressed_desk->texture[0].type =
467 theme->a_unfocused_pressed_set_desk->texture[0].type =
468 theme->a_disabled_focused_shade->texture[0].type =
469 theme->a_disabled_unfocused_shade->texture[0].type =
470 theme->a_focused_unpressed_shade->texture[0].type =
471 theme->a_focused_pressed_shade->texture[0].type =
472 theme->a_focused_pressed_set_shade->texture[0].type =
473 theme->a_unfocused_unpressed_shade->texture[0].type =
474 theme->a_unfocused_pressed_shade->texture[0].type =
475 theme->a_unfocused_pressed_set_shade->texture[0].type =
476 theme->a_disabled_focused_iconify->texture[0].type =
477 theme->a_disabled_unfocused_iconify->texture[0].type =
478 theme->a_focused_unpressed_iconify->texture[0].type =
479 theme->a_focused_pressed_iconify->texture[0].type =
480 theme->a_unfocused_unpressed_iconify->texture[0].type =
481 theme->a_unfocused_pressed_iconify->texture[0].type = RR_TEXTURE_MASK;
482 theme->a_disabled_focused_max->texture[0].data.mask.mask =
483 theme->a_disabled_unfocused_max->texture[0].data.mask.mask =
484 theme->a_focused_unpressed_max->texture[0].data.mask.mask =
485 theme->a_unfocused_unpressed_max->texture[0].data.mask.mask =
486 theme->a_focused_pressed_max->texture[0].data.mask.mask =
487 theme->a_unfocused_pressed_max->texture[0].data.mask.mask =
488 theme->max_unset_mask;
489 theme->a_focused_pressed_set_max->texture[0].data.mask.mask =
490 theme->a_unfocused_pressed_set_max->texture[0].data.mask.mask =
491 theme->max_set_mask;
492 theme->a_disabled_focused_close->texture[0].data.mask.mask =
493 theme->a_disabled_unfocused_close->texture[0].data.mask.mask =
494 theme->a_focused_pressed_close->texture[0].data.mask.mask =
495 theme->a_unfocused_pressed_close->texture[0].data.mask.mask =
496 theme->a_focused_unpressed_close->texture[0].data.mask.mask =
497 theme->a_unfocused_unpressed_close->texture[0].data.mask.mask =
498 theme->close_mask;
499 theme->a_disabled_focused_desk->texture[0].data.mask.mask =
500 theme->a_disabled_unfocused_desk->texture[0].data.mask.mask =
501 theme->a_focused_unpressed_desk->texture[0].data.mask.mask =
502 theme->a_unfocused_unpressed_desk->texture[0].data.mask.mask =
503 theme->a_focused_pressed_desk->texture[0].data.mask.mask =
504 theme->a_unfocused_pressed_desk->texture[0].data.mask.mask =
505 theme->desk_unset_mask;
506 theme->a_focused_pressed_set_desk->texture[0].data.mask.mask =
507 theme->a_unfocused_pressed_set_desk->texture[0].data.mask.mask =
508 theme->desk_set_mask;
509 theme->a_disabled_focused_shade->texture[0].data.mask.mask =
510 theme->a_disabled_unfocused_shade->texture[0].data.mask.mask =
511 theme->a_focused_unpressed_shade->texture[0].data.mask.mask =
512 theme->a_unfocused_unpressed_shade->texture[0].data.mask.mask =
513 theme->a_focused_pressed_shade->texture[0].data.mask.mask =
514 theme->a_unfocused_pressed_shade->texture[0].data.mask.mask =
515 theme->shade_unset_mask;
516 theme->a_focused_pressed_set_shade->texture[0].data.mask.mask =
517 theme->a_unfocused_pressed_set_shade->texture[0].data.mask.mask =
518 theme->shade_set_mask;
519 theme->a_disabled_focused_iconify->texture[0].data.mask.mask =
520 theme->a_disabled_unfocused_iconify->texture[0].data.mask.mask =
521 theme->a_focused_unpressed_iconify->texture[0].data.mask.mask =
522 theme->a_unfocused_unpressed_iconify->texture[0].data.mask.mask =
523 theme->a_focused_pressed_iconify->texture[0].data.mask.mask =
524 theme->a_unfocused_pressed_iconify->texture[0].data.mask.mask =
525 theme->iconify_mask;
526 theme->a_disabled_focused_max->texture[0].data.mask.color =
527 theme->a_disabled_focused_close->texture[0].data.mask.color =
528 theme->a_disabled_focused_desk->texture[0].data.mask.color =
529 theme->a_disabled_focused_shade->texture[0].data.mask.color =
530 theme->a_disabled_focused_iconify->texture[0].data.mask.color =
531 theme->titlebut_disabled_focused_color;
532 theme->a_disabled_unfocused_max->texture[0].data.mask.color =
533 theme->a_disabled_unfocused_close->texture[0].data.mask.color =
534 theme->a_disabled_unfocused_desk->texture[0].data.mask.color =
535 theme->a_disabled_unfocused_shade->texture[0].data.mask.color =
536 theme->a_disabled_unfocused_iconify->texture[0].data.mask.color =
537 theme->titlebut_disabled_unfocused_color;
538 theme->a_focused_unpressed_max->texture[0].data.mask.color =
539 theme->a_focused_pressed_max->texture[0].data.mask.color =
540 theme->a_focused_pressed_set_max->texture[0].data.mask.color =
541 theme->a_focused_unpressed_close->texture[0].data.mask.color =
542 theme->a_focused_pressed_close->texture[0].data.mask.color =
543 theme->a_focused_unpressed_desk->texture[0].data.mask.color =
544 theme->a_focused_pressed_desk->texture[0].data.mask.color =
545 theme->a_focused_pressed_set_desk->texture[0].data.mask.color =
546 theme->a_focused_unpressed_shade->texture[0].data.mask.color =
547 theme->a_focused_pressed_shade->texture[0].data.mask.color =
548 theme->a_focused_pressed_set_shade->texture[0].data.mask.color =
549 theme->a_focused_unpressed_iconify->texture[0].data.mask.color =
550 theme->a_focused_pressed_iconify->texture[0].data.mask.color =
551 theme->titlebut_focused_color;
552 theme->a_unfocused_unpressed_max->texture[0].data.mask.color =
553 theme->a_unfocused_pressed_max->texture[0].data.mask.color =
554 theme->a_unfocused_pressed_set_max->texture[0].data.mask.color =
555 theme->a_unfocused_unpressed_close->texture[0].data.mask.color =
556 theme->a_unfocused_pressed_close->texture[0].data.mask.color =
557 theme->a_unfocused_unpressed_desk->texture[0].data.mask.color =
558 theme->a_unfocused_pressed_desk->texture[0].data.mask.color =
559 theme->a_unfocused_pressed_set_desk->texture[0].data.mask.color =
560 theme->a_unfocused_unpressed_shade->texture[0].data.mask.color =
561 theme->a_unfocused_pressed_shade->texture[0].data.mask.color =
562 theme->a_unfocused_pressed_set_shade->texture[0].data.mask.color =
563 theme->a_unfocused_unpressed_iconify->texture[0].data.mask.color =
564 theme->a_unfocused_pressed_iconify->texture[0].data.mask.color =
565 theme->titlebut_unfocused_color;
566
567 XrmDestroyDatabase(db);
568
569 theme->label_height = theme->winfont_height;
570 theme->title_height = theme->label_height + theme->bevel * 2;
571 theme->button_size = theme->label_height - 2;
572 theme->grip_width = theme->button_size * 2;
573
574 return theme;
575 }
576
577 void RrThemeFree(RrTheme *theme)
578 {
579 if (theme) {
580 g_free(theme->name);
581
582 RrColorFree(theme->b_color);
583 RrColorFree(theme->cb_unfocused_color);
584 RrColorFree(theme->cb_focused_color);
585 RrColorFree(theme->title_unfocused_color);
586 RrColorFree(theme->title_focused_color);
587 RrColorFree(theme->titlebut_unfocused_color);
588 RrColorFree(theme->titlebut_focused_color);
589 RrColorFree(theme->menu_color);
590 RrColorFree(theme->menu_title_color);
591 RrColorFree(theme->menu_disabled_color);
592 RrColorFree(theme->menu_hilite_color);
593
594 RrPixmapMaskFree(theme->max_set_mask);
595 RrPixmapMaskFree(theme->max_unset_mask);
596 RrPixmapMaskFree(theme->desk_set_mask);
597 RrPixmapMaskFree(theme->desk_unset_mask);
598 RrPixmapMaskFree(theme->shade_set_mask);
599 RrPixmapMaskFree(theme->shade_unset_mask);
600 RrPixmapMaskFree(theme->iconify_mask);
601 RrPixmapMaskFree(theme->close_mask);
602
603 RrFontClose(theme->winfont);
604 RrFontClose(theme->mtitlefont);
605 RrFontClose(theme->mfont);
606
607 g_free(theme->title_layout);
608
609 RrAppearanceFree(theme->a_focused_unpressed_max);
610 RrAppearanceFree(theme->a_focused_pressed_max);
611 RrAppearanceFree(theme->a_focused_pressed_set_max);
612 RrAppearanceFree(theme->a_unfocused_unpressed_max);
613 RrAppearanceFree(theme->a_unfocused_pressed_max);
614 RrAppearanceFree(theme->a_unfocused_pressed_set_max);
615 RrAppearanceFree(theme->a_focused_unpressed_close);
616 RrAppearanceFree(theme->a_focused_pressed_close);
617 RrAppearanceFree(theme->a_unfocused_unpressed_close);
618 RrAppearanceFree(theme->a_unfocused_pressed_close);
619 RrAppearanceFree(theme->a_focused_unpressed_desk);
620 RrAppearanceFree(theme->a_focused_pressed_desk);
621 RrAppearanceFree(theme->a_unfocused_unpressed_desk);
622 RrAppearanceFree(theme->a_unfocused_pressed_desk);
623 RrAppearanceFree(theme->a_focused_unpressed_shade);
624 RrAppearanceFree(theme->a_focused_pressed_shade);
625 RrAppearanceFree(theme->a_unfocused_unpressed_shade);
626 RrAppearanceFree(theme->a_unfocused_pressed_shade);
627 RrAppearanceFree(theme->a_focused_unpressed_iconify);
628 RrAppearanceFree(theme->a_focused_pressed_iconify);
629 RrAppearanceFree(theme->a_unfocused_unpressed_iconify);
630 RrAppearanceFree(theme->a_unfocused_pressed_iconify);
631 RrAppearanceFree(theme->a_focused_grip);
632 RrAppearanceFree(theme->a_unfocused_grip);
633 RrAppearanceFree(theme->a_focused_title);
634 RrAppearanceFree(theme->a_unfocused_title);
635 RrAppearanceFree(theme->a_focused_label);
636 RrAppearanceFree(theme->a_unfocused_label);
637 RrAppearanceFree(theme->a_icon);
638 RrAppearanceFree(theme->a_focused_handle);
639 RrAppearanceFree(theme->a_unfocused_handle);
640 RrAppearanceFree(theme->a_menu);
641 RrAppearanceFree(theme->a_menu_title);
642 RrAppearanceFree(theme->a_menu_item);
643 RrAppearanceFree(theme->a_menu_disabled);
644 RrAppearanceFree(theme->a_menu_hilite);
645 RrAppearanceFree(theme->app_hilite_bg);
646 RrAppearanceFree(theme->app_unhilite_bg);
647 RrAppearanceFree(theme->app_hilite_label);
648 RrAppearanceFree(theme->app_unhilite_label);
649 RrAppearanceFree(theme->app_icon);
650 }
651 }
652
653 static XrmDatabase loaddb(RrTheme *theme, char *name)
654 {
655 XrmDatabase db;
656
657 if ((db = XrmGetFileDatabase(name)))
658 theme->path = g_path_get_dirname(name);
659 if (db == NULL) {
660 char *s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
661 name, NULL);
662 if ((db = XrmGetFileDatabase(s)))
663 theme->path = g_path_get_dirname(s);
664 g_free(s);
665 }
666 if (db == NULL) {
667 char *s = g_build_filename(THEMEDIR, name, NULL);
668 if ((db = XrmGetFileDatabase(s)))
669 theme->path = g_path_get_dirname(s);
670 g_free(s);
671 }
672
673 return db;
674 }
675
676 static char *create_class_name(char *rname)
677 {
678 char *rclass = g_strdup(rname);
679 char *p = rclass;
680
681 while (TRUE) {
682 *p = toupper(*p);
683 p = strchr(p+1, '.');
684 if (p == NULL) break;
685 ++p;
686 if (*p == '\0') break;
687 }
688 return rclass;
689 }
690
691 static gboolean read_int(XrmDatabase db, char *rname, int *value)
692 {
693 gboolean ret = FALSE;
694 char *rclass = create_class_name(rname);
695 char *rettype, *end;
696 XrmValue retvalue;
697
698 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
699 retvalue.addr != NULL) {
700 *value = (int)strtol(retvalue.addr, &end, 10);
701 if (end != retvalue.addr)
702 ret = TRUE;
703 }
704
705 g_free(rclass);
706 return ret;
707 }
708
709 static gboolean read_string(XrmDatabase db, char *rname, char **value)
710 {
711 gboolean ret = FALSE;
712 char *rclass = create_class_name(rname);
713 char *rettype;
714 XrmValue retvalue;
715
716 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
717 retvalue.addr != NULL) {
718 *value = retvalue.addr;
719 ret = TRUE;
720 }
721
722 g_free(rclass);
723 return ret;
724 }
725
726 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
727 gchar *rname, RrColor **value)
728 {
729 gboolean ret = FALSE;
730 char *rclass = create_class_name(rname);
731 char *rettype;
732 XrmValue retvalue;
733
734 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
735 retvalue.addr != NULL) {
736 RrColor *c = RrColorParse(inst, retvalue.addr);
737 if (c != NULL) {
738 *value = c;
739 ret = TRUE;
740 }
741 }
742
743 g_free(rclass);
744 return ret;
745 }
746
747 static gboolean read_mask(const RrInstance *inst,
748 gchar *maskname, RrTheme *theme,
749 RrPixmapMask **value)
750 {
751 gboolean ret = FALSE;
752 char *s;
753 char *data_dir;
754 int hx, hy; /* ignored */
755 unsigned int w, h;
756 unsigned char *b;
757
758 data_dir = g_strdup_printf("%s_data", theme->name);
759
760 s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
761 data_dir, maskname, NULL);
762 if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess)
763 ret = TRUE;
764 else {
765 g_free(s);
766 s = g_build_filename(THEMEDIR, data_dir, maskname, NULL);
767 if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess)
768 ret = TRUE;
769 else {
770 g_free(s);
771 s = g_build_filename(theme->path, data_dir, maskname, NULL);
772 if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess)
773 ret = TRUE;
774 }
775 }
776
777 if (ret) {
778 *value = RrPixmapMaskNew(inst, w, h, (char*)b);
779 XFree(b);
780 }
781
782 g_free(s);
783 g_free(data_dir);
784
785 return ret;
786 }
787
788 static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
789 RrReliefType *relief, RrBevelType *bevel,
790 gboolean *interlaced, gboolean *border)
791 {
792 char *t;
793
794 /* convert to all lowercase */
795 for (t = tex; *t != '\0'; ++t)
796 *t = g_ascii_tolower(*t);
797
798 if (strstr(tex, "parentrelative") != NULL) {
799 *grad = RR_SURFACE_PARENTREL;
800 } else {
801 if (strstr(tex, "gradient") != NULL) {
802 if (strstr(tex, "crossdiagonal") != NULL)
803 *grad = RR_SURFACE_CROSS_DIAGONAL;
804 else if (strstr(tex, "pyramid") != NULL)
805 *grad = RR_SURFACE_PYRAMID;
806 else if (strstr(tex, "horizontal") != NULL)
807 *grad = RR_SURFACE_HORIZONTAL;
808 else if (strstr(tex, "vertical") != NULL)
809 *grad = RR_SURFACE_VERTICAL;
810 else
811 *grad = RR_SURFACE_DIAGONAL;
812 } else {
813 *grad = RR_SURFACE_SOLID;
814 }
815
816 if (strstr(tex, "sunken") != NULL)
817 *relief = RR_RELIEF_SUNKEN;
818 else if (strstr(tex, "flat") != NULL)
819 *relief = RR_RELIEF_FLAT;
820 else
821 *relief = RR_RELIEF_RAISED;
822
823 *border = FALSE;
824 if (*relief == RR_RELIEF_FLAT) {
825 if (strstr(tex, "border") != NULL)
826 *border = TRUE;
827 } else {
828 if (strstr(tex, "bevel2") != NULL)
829 *bevel = RR_BEVEL_2;
830 else
831 *bevel = RR_BEVEL_1;
832 }
833
834 if (strstr(tex, "interlaced") != NULL)
835 *interlaced = TRUE;
836 else
837 *interlaced = FALSE;
838 }
839 }
840
841
842 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
843 gchar *rname, RrAppearance *value)
844 {
845 gboolean ret = FALSE;
846 char *rclass = create_class_name(rname), *cname, *ctoname, *bcname;
847 char *rettype;
848 XrmValue retvalue;
849
850 cname = g_strconcat(rname, ".color", NULL);
851 ctoname = g_strconcat(rname, ".colorTo", NULL);
852 bcname = g_strconcat(rname, ".borderColor", NULL);
853
854 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
855 retvalue.addr != NULL) {
856 parse_appearance(retvalue.addr,
857 &value->surface.grad,
858 &value->surface.relief,
859 &value->surface.bevel,
860 &value->surface.interlaced,
861 &value->surface.border);
862 if (!read_color(db, inst, cname, &value->surface.primary))
863 value->surface.primary = RrColorNew(inst, 0, 0, 0);
864 if (!read_color(db, inst, ctoname, &value->surface.secondary))
865 value->surface.secondary = RrColorNew(inst, 0, 0, 0);
866 if (value->surface.border)
867 if (!read_color(db, inst, bcname,
868 &value->surface.border_color))
869 value->surface.border_color = RrColorNew(inst, 0, 0, 0);
870 ret = TRUE;
871 }
872
873 g_free(bcname);
874 g_free(ctoname);
875 g_free(cname);
876 g_free(rclass);
877 return ret;
878 }
879
880 static void set_default_appearance(RrAppearance *a)
881 {
882 a->surface.grad = RR_SURFACE_SOLID;
883 a->surface.relief = RR_RELIEF_FLAT;
884 a->surface.bevel = RR_BEVEL_1;
885 a->surface.interlaced = FALSE;
886 a->surface.border = FALSE;
887 a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
888 a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
889 }
This page took 0.081615 seconds and 5 git commands to generate.