Strip leading/trailing whitespace when parsing colors and other strings (bug #4937)
[dana/openbox.git] / openbox / framerender.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    framerender.c for the Openbox window manager
4    Copyright (c) 2006        Mikael Magnusson
5    Copyright (c) 2003-2007   Dana Jansens
6
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.
11
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.
16
17    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "frame.h"
21 #include "openbox.h"
22 #include "screen.h"
23 #include "client.h"
24 #include "framerender.h"
25 #include "obrender/theme.h"
26
27 static void framerender_label(ObFrame *self, RrAppearance *a);
28 static void framerender_icon(ObFrame *self, RrAppearance *a);
29 static void framerender_max(ObFrame *self, RrAppearance *a);
30 static void framerender_iconify(ObFrame *self, RrAppearance *a);
31 static void framerender_desk(ObFrame *self, RrAppearance *a);
32 static void framerender_shade(ObFrame *self, RrAppearance *a);
33 static void framerender_close(ObFrame *self, RrAppearance *a);
34
35 void framerender_frame(ObFrame *self)
36 {
37     if (frame_iconify_animating(self))
38         return; /* delay redrawing until the animation is done */
39     if (!self->need_render)
40         return;
41     if (!self->visible)
42         return;
43     self->need_render = FALSE;
44
45     {
46         gulong px;
47
48         px = (self->focused ?
49               RrColorPixel(ob_rr_theme->cb_focused_color) :
50               RrColorPixel(ob_rr_theme->cb_unfocused_color));
51
52         XSetWindowBackground(obt_display, self->backback, px);
53         XClearWindow(obt_display, self->backback);
54         XSetWindowBackground(obt_display, self->innerleft, px);
55         XClearWindow(obt_display, self->innerleft);
56         XSetWindowBackground(obt_display, self->innertop, px);
57         XClearWindow(obt_display, self->innertop);
58         XSetWindowBackground(obt_display, self->innerright, px);
59         XClearWindow(obt_display, self->innerright);
60         XSetWindowBackground(obt_display, self->innerbottom, px);
61         XClearWindow(obt_display, self->innerbottom);
62         XSetWindowBackground(obt_display, self->innerbll, px);
63         XClearWindow(obt_display, self->innerbll);
64         XSetWindowBackground(obt_display, self->innerbrr, px);
65         XClearWindow(obt_display, self->innerbrr);
66         XSetWindowBackground(obt_display, self->innerblb, px);
67         XClearWindow(obt_display, self->innerblb);
68         XSetWindowBackground(obt_display, self->innerbrb, px);
69         XClearWindow(obt_display, self->innerbrb);
70
71         px = RrColorPixel(self->focused ?
72             (self->client->undecorated ?
73              ob_rr_theme->frame_undecorated_focused_border_color :
74              ob_rr_theme->frame_focused_border_color) :
75             (self->client->undecorated ?
76              ob_rr_theme->frame_undecorated_unfocused_border_color :
77              ob_rr_theme->frame_unfocused_border_color));
78
79         XSetWindowBackground(obt_display, self->left, px);
80         XClearWindow(obt_display, self->left);
81         XSetWindowBackground(obt_display, self->right, px);
82         XClearWindow(obt_display, self->right);
83
84         XSetWindowBackground(obt_display, self->titleleft, px);
85         XClearWindow(obt_display, self->titleleft);
86         XSetWindowBackground(obt_display, self->titletop, px);
87         XClearWindow(obt_display, self->titletop);
88         XSetWindowBackground(obt_display, self->titletopleft, px);
89         XClearWindow(obt_display, self->titletopleft);
90         XSetWindowBackground(obt_display, self->titletopright, px);
91         XClearWindow(obt_display, self->titletopright);
92         XSetWindowBackground(obt_display, self->titleright, px);
93         XClearWindow(obt_display, self->titleright);
94
95         XSetWindowBackground(obt_display, self->handleleft, px);
96         XClearWindow(obt_display, self->handleleft);
97         XSetWindowBackground(obt_display, self->handletop, px);
98         XClearWindow(obt_display, self->handletop);
99         XSetWindowBackground(obt_display, self->handleright, px);
100         XClearWindow(obt_display, self->handleright);
101         XSetWindowBackground(obt_display, self->handlebottom, px);
102         XClearWindow(obt_display, self->handlebottom);
103
104         XSetWindowBackground(obt_display, self->lgripleft, px);
105         XClearWindow(obt_display, self->lgripleft);
106         XSetWindowBackground(obt_display, self->lgriptop, px);
107         XClearWindow(obt_display, self->lgriptop);
108         XSetWindowBackground(obt_display, self->lgripbottom, px);
109         XClearWindow(obt_display, self->lgripbottom);
110
111         XSetWindowBackground(obt_display, self->rgripright, px);
112         XClearWindow(obt_display, self->rgripright);
113         XSetWindowBackground(obt_display, self->rgriptop, px);
114         XClearWindow(obt_display, self->rgriptop);
115         XSetWindowBackground(obt_display, self->rgripbottom, px);
116         XClearWindow(obt_display, self->rgripbottom);
117
118         /* don't use the separator color for shaded windows */
119         if (!self->client->shaded)
120             px = (self->focused ?
121                   RrColorPixel(ob_rr_theme->title_separator_focused_color) :
122                   RrColorPixel(ob_rr_theme->title_separator_unfocused_color));
123
124         XSetWindowBackground(obt_display, self->titlebottom, px);
125         XClearWindow(obt_display, self->titlebottom);
126     }
127
128     if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
129         RrAppearance *t, *l, *m, *n, *i, *d, *s, *c, *clear;
130         if (self->focused) {
131             t = ob_rr_theme->a_focused_title;
132             l = ob_rr_theme->a_focused_label;
133             m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
134                  ob_rr_theme->btn_max->a_disabled_focused :
135                  (self->client->max_vert || self->client->max_horz ?
136                   (self->max_press ?
137                    ob_rr_theme->btn_max->a_toggled_focused_pressed :
138                    (self->max_hover ?
139                     ob_rr_theme->btn_max->a_toggled_hover_focused :
140                     ob_rr_theme->btn_max->a_toggled_focused_unpressed)) :
141                   (self->max_press ?
142                    ob_rr_theme->btn_max->a_focused_pressed :
143                    (self->max_hover ?
144                     ob_rr_theme->btn_max->a_hover_focused :
145                     ob_rr_theme->btn_max->a_focused_unpressed))));
146             n = ob_rr_theme->a_icon;
147             i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
148                  ob_rr_theme->btn_iconify->a_disabled_focused :
149                  (self->iconify_press ?
150                   ob_rr_theme->btn_iconify->a_focused_pressed :
151                   (self->iconify_hover ?
152                    ob_rr_theme->btn_iconify->a_hover_focused :
153                    ob_rr_theme->btn_iconify->a_focused_unpressed)));
154             d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
155                  ob_rr_theme->btn_desk->a_disabled_focused :
156                  (self->client->desktop == DESKTOP_ALL ?
157                   (self->desk_press ?
158                    ob_rr_theme->btn_desk->a_toggled_focused_pressed :
159                    (self->desk_hover ?
160                     ob_rr_theme->btn_desk->a_toggled_hover_focused :
161                     ob_rr_theme->btn_desk->a_toggled_focused_unpressed)) :
162                   (self->desk_press ?
163                    ob_rr_theme->btn_desk->a_focused_pressed :
164                    (self->desk_hover ?
165                     ob_rr_theme->btn_desk->a_hover_focused :
166                     ob_rr_theme->btn_desk->a_focused_unpressed))));
167             s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
168                  ob_rr_theme->btn_shade->a_disabled_focused :
169                  (self->client->shaded ?
170                   (self->shade_press ?
171                    ob_rr_theme->btn_shade->a_toggled_focused_pressed :
172                    (self->shade_hover ?
173                     ob_rr_theme->btn_shade->a_toggled_hover_focused :
174                     ob_rr_theme->btn_shade->a_toggled_focused_unpressed)) :
175                   (self->shade_press ?
176                    ob_rr_theme->btn_shade->a_focused_pressed :
177                    (self->shade_hover ?
178                     ob_rr_theme->btn_shade->a_hover_focused :
179                     ob_rr_theme->btn_shade->a_focused_unpressed))));
180             c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
181                  ob_rr_theme->btn_close->a_disabled_focused :
182                  (self->close_press ?
183                   ob_rr_theme->btn_close->a_focused_pressed :
184                   (self->close_hover ?
185                    ob_rr_theme->btn_close->a_hover_focused :
186                    ob_rr_theme->btn_close->a_focused_unpressed)));
187         } else {
188             t = ob_rr_theme->a_unfocused_title;
189             l = ob_rr_theme->a_unfocused_label;
190             m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
191                  ob_rr_theme->btn_max->a_disabled_unfocused :
192                  (self->client->max_vert || self->client->max_horz ?
193                   (self->max_press ?
194                    ob_rr_theme->btn_max->a_toggled_unfocused_pressed :
195                    (self->max_hover ?
196                     ob_rr_theme->btn_max->a_toggled_hover_unfocused :
197                     ob_rr_theme->btn_max->a_toggled_unfocused_unpressed)) :
198                   (self->max_press ?
199                    ob_rr_theme->btn_max->a_unfocused_pressed :
200                    (self->max_hover ?
201                     ob_rr_theme->btn_max->a_hover_unfocused :
202                     ob_rr_theme->btn_max->a_unfocused_unpressed))));
203             n = ob_rr_theme->a_icon;
204             i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
205                  ob_rr_theme->btn_iconify->a_disabled_unfocused :
206                  (self->iconify_press ?
207                   ob_rr_theme->btn_iconify->a_unfocused_pressed :
208                   (self->iconify_hover ?
209                    ob_rr_theme->btn_iconify->a_hover_unfocused :
210                    ob_rr_theme->btn_iconify->a_unfocused_unpressed)));
211             d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
212                  ob_rr_theme->btn_desk->a_disabled_unfocused :
213                  (self->client->desktop == DESKTOP_ALL ?
214                   (self->desk_press ?
215                    ob_rr_theme->btn_desk->a_toggled_unfocused_pressed :
216                    (self->desk_hover ?
217                     ob_rr_theme->btn_desk->a_toggled_hover_unfocused :
218                     ob_rr_theme->btn_desk->a_toggled_unfocused_unpressed)) :
219                   (self->desk_press ?
220                    ob_rr_theme->btn_desk->a_unfocused_pressed :
221                    (self->desk_hover ?
222                     ob_rr_theme->btn_desk->a_hover_unfocused :
223                     ob_rr_theme->btn_desk->a_unfocused_unpressed))));
224             s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
225                  ob_rr_theme->btn_shade->a_disabled_unfocused :
226                  (self->client->shaded ?
227                   (self->shade_press ?
228                    ob_rr_theme->btn_shade->a_toggled_unfocused_pressed :
229                    (self->shade_hover ?
230                     ob_rr_theme->btn_shade->a_toggled_hover_unfocused :
231                     ob_rr_theme->btn_shade->a_toggled_unfocused_unpressed)) :
232                   (self->shade_press ?
233                    ob_rr_theme->btn_shade->a_unfocused_pressed :
234                    (self->shade_hover ?
235                     ob_rr_theme->btn_shade->a_hover_unfocused :
236                     ob_rr_theme->btn_shade->a_unfocused_unpressed))));
237             c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
238                  ob_rr_theme->btn_close->a_disabled_unfocused :
239                  (self->close_press ?
240                   ob_rr_theme->btn_close->a_unfocused_pressed :
241                   (self->close_hover ?
242                    ob_rr_theme->btn_close->a_hover_unfocused :
243                    ob_rr_theme->btn_close->a_unfocused_unpressed)));
244         }
245         clear = ob_rr_theme->a_clear;
246
247         RrPaint(t, self->title, self->width, ob_rr_theme->title_height);
248
249         clear->surface.parent = t;
250         clear->surface.parenty = 0;
251
252         clear->surface.parentx = ob_rr_theme->grip_width;
253
254         RrPaint(clear, self->topresize,
255                 self->width - ob_rr_theme->grip_width * 2,
256                 ob_rr_theme->paddingy + 1);
257
258         clear->surface.parentx = 0;
259
260         if (ob_rr_theme->grip_width > 0)
261             RrPaint(clear, self->tltresize,
262                     ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
263         if (ob_rr_theme->title_height > 0)
264             RrPaint(clear, self->tllresize,
265                     ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
266
267         clear->surface.parentx = self->width - ob_rr_theme->grip_width;
268
269         if (ob_rr_theme->grip_width > 0)
270             RrPaint(clear, self->trtresize,
271                     ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
272
273         clear->surface.parentx = self->width - (ob_rr_theme->paddingx + 1);
274
275         if (ob_rr_theme->title_height > 0)
276             RrPaint(clear, self->trrresize,
277                     ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
278
279         /* set parents for any parent relative guys */
280         l->surface.parent = t;
281         l->surface.parentx = self->label_x;
282         l->surface.parenty = ob_rr_theme->paddingy;
283
284         m->surface.parent = t;
285         m->surface.parentx = self->max_x;
286         m->surface.parenty = ob_rr_theme->paddingy + 1;
287
288         n->surface.parent = t;
289         n->surface.parentx = self->icon_x;
290         n->surface.parenty = ob_rr_theme->paddingy;
291
292         i->surface.parent = t;
293         i->surface.parentx = self->iconify_x;
294         i->surface.parenty = ob_rr_theme->paddingy + 1;
295
296         d->surface.parent = t;
297         d->surface.parentx = self->desk_x;
298         d->surface.parenty = ob_rr_theme->paddingy + 1;
299
300         s->surface.parent = t;
301         s->surface.parentx = self->shade_x;
302         s->surface.parenty = ob_rr_theme->paddingy + 1;
303
304         c->surface.parent = t;
305         c->surface.parentx = self->close_x;
306         c->surface.parenty = ob_rr_theme->paddingy + 1;
307
308         framerender_label(self, l);
309         framerender_max(self, m);
310         framerender_icon(self, n);
311         framerender_iconify(self, i);
312         framerender_desk(self, d);
313         framerender_shade(self, s);
314         framerender_close(self, c);
315     }
316
317     if (self->decorations & OB_FRAME_DECOR_HANDLE &&
318         ob_rr_theme->handle_height > 0)
319     {
320         RrAppearance *h, *g;
321
322         h = (self->focused ?
323              ob_rr_theme->a_focused_handle : ob_rr_theme->a_unfocused_handle);
324
325         RrPaint(h, self->handle, self->width, ob_rr_theme->handle_height);
326
327         if (self->decorations & OB_FRAME_DECOR_GRIPS) {
328             g = (self->focused ?
329                  ob_rr_theme->a_focused_grip : ob_rr_theme->a_unfocused_grip);
330
331             if (g->surface.grad == RR_SURFACE_PARENTREL)
332                 g->surface.parent = h;
333
334             g->surface.parentx = 0;
335             g->surface.parenty = 0;
336
337             RrPaint(g, self->lgrip,
338                     ob_rr_theme->grip_width, ob_rr_theme->handle_height);
339
340             g->surface.parentx = self->width - ob_rr_theme->grip_width;
341             g->surface.parenty = 0;
342
343             RrPaint(g, self->rgrip,
344                     ob_rr_theme->grip_width, ob_rr_theme->handle_height);
345         }
346     }
347
348     XFlush(obt_display);
349 }
350
351 static void framerender_label(ObFrame *self, RrAppearance *a)
352 {
353     if (!self->label_on) return;
354     /* set the texture's text! */
355     a->texture[0].data.text.string = self->client->title;
356     RrPaint(a, self->label, self->label_width, ob_rr_theme->label_height);
357 }
358
359 static void framerender_icon(ObFrame *self, RrAppearance *a)
360 {
361     RrImage *icon;
362
363     if (!self->icon_on) return;
364
365     icon = client_icon(self->client);
366
367     if (icon) {
368         RrAppearanceClearTextures(a);
369         a->texture[0].type = RR_TEXTURE_IMAGE;
370         a->texture[0].data.image.alpha = 0xff;
371         a->texture[0].data.image.image = icon;
372     } else {
373         RrAppearanceClearTextures(a);
374         a->texture[0].type = RR_TEXTURE_NONE;
375     }
376
377     RrPaint(a, self->icon,
378             ob_rr_theme->button_size + 2, ob_rr_theme->button_size + 2);
379 }
380
381 static void framerender_max(ObFrame *self, RrAppearance *a)
382 {
383     if (!self->max_on) return;
384     RrPaint(a, self->max, ob_rr_theme->button_size, ob_rr_theme->button_size);
385 }
386
387 static void framerender_iconify(ObFrame *self, RrAppearance *a)
388 {
389     if (!self->iconify_on) return;
390     RrPaint(a, self->iconify,
391             ob_rr_theme->button_size, ob_rr_theme->button_size);
392 }
393
394 static void framerender_desk(ObFrame *self, RrAppearance *a)
395 {
396     if (!self->desk_on) return;
397     RrPaint(a, self->desk, ob_rr_theme->button_size, ob_rr_theme->button_size);
398 }
399
400 static void framerender_shade(ObFrame *self, RrAppearance *a)
401 {
402     if (!self->shade_on) return;
403     RrPaint(a, self->shade,
404             ob_rr_theme->button_size, ob_rr_theme->button_size);
405 }
406
407 static void framerender_close(ObFrame *self, RrAppearance *a)
408 {
409     if (!self->close_on) return;
410     RrPaint(a, self->close,
411             ob_rr_theme->button_size, ob_rr_theme->button_size);
412 }