]> Dogcows Code - chaz/tint2/blob - src/util/area.c
fixed Issue 282
[chaz/tint2] / src / util / area.c
1 /**************************************************************************
2 *
3 * Tint2 : area
4 *
5 * Copyright (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **************************************************************************/
19
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include <X11/Xatom.h>
23 #include <X11/extensions/Xrender.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <pango/pangocairo.h>
28
29 #include "area.h"
30 #include "server.h"
31 #include "panel.h"
32
33
34 /*
35 // TODO : layering & drawing loop
36 1) browse tree and resize SIZE_BY_CONTENT node
37 - children node are resized before its parent
38 - if 'size' changed then 'resize = 1' on the parent
39 2) browse tree and resize SIZE_BY_LAYOUT node
40 - parent node is resized before its children
41 - if 'size' changed then 'resize = 1' on childs with SIZE_BY_LAYOUT
42 3) calculate posx of all objects
43 4) redraw needed objects
44 */
45
46 void refresh (Area *a)
47 {
48 // don't draw and resize hide objects
49 if (!a->on_screen) return;
50
51 size(a);
52 //size_by_content(a);
53
54 // don't draw transparent objects (without foreground and without background)
55 if (a->redraw) {
56 a->redraw = 0;
57 // force redraw of child
58 GSList *l;
59 for (l = a->list ; l ; l = l->next)
60 set_redraw(l->data);
61
62 //printf("draw area posx %d, width %d\n", a->posx, a->width);
63 draw(a);
64 }
65
66 // draw current Area
67 if (a->pix == 0) printf("empty area posx %d, width %d\n", a->posx, a->width);
68 XCopyArea (server.dsp, a->pix, ((Panel *)a->panel)->temp_pmap, server.gc, 0, 0, a->width, a->height, a->posx, a->posy);
69
70 // and then refresh child object
71 GSList *l;
72 for (l = a->list; l ; l = l->next)
73 refresh(l->data);
74 }
75
76
77 void size (Area *a)
78 {
79 GSList *l;
80
81 if (a->resize) {
82 a->resize = 0;
83 // force the resize of childs
84 for (l = a->list; l ; l = l->next) {
85 Area *area = (Area*)l->data;
86 area->resize = 1;
87 size(area);
88 }
89
90 // resize can generate a redraw
91 if (a->_resize)
92 a->_resize(a);
93 }
94 }
95
96 // browse tree and resize SIZE_BY_CONTENT node
97 void size_by_content (Area *a)
98 {
99 // children node are resized before its parent
100 GSList *l;
101 for (l = a->list; l ; l = l->next)
102 size_by_content(l->data);
103
104 // calculate current area's size
105 if (a->resize && a->size_mode == SIZE_BY_CONTENT) {
106 a->resize = 0;
107
108 // if 'size' changed then 'resize = 1' on the parent
109 a->_resize(a);
110 ((Area*)a->parent)->resize = 1;
111 }
112 }
113
114
115 // browse tree and resize SIZE_BY_LAYOUT node
116 void size_by_layout (Area *a)
117 {
118 // parent node is resized before its children
119
120 // calculate current area's size
121 if (a->resize && a->size_mode == SIZE_BY_LAYOUT) {
122 a->resize = 0;
123
124 // if 'size' changed then 'resize = 1' on the parent
125 //if (a->_resize(a))
126 //a->parent->resize = 1;
127 }
128
129 GSList *l;
130 for (l = a->list; l ; l = l->next)
131 size_by_layout(l->data);
132 }
133
134
135 void set_redraw (Area *a)
136 {
137 a->redraw = 1;
138
139 GSList *l;
140 for (l = a->list ; l ; l = l->next)
141 set_redraw(l->data);
142 }
143
144
145 void draw (Area *a)
146 {
147 if (a->pix) XFreePixmap (server.dsp, a->pix);
148 a->pix = XCreatePixmap (server.dsp, server.root_win, a->width, a->height, server.depth);
149
150 // add layer of root pixmap (or clear pixmap if real_transparency==true)
151 if (server.real_transparency)
152 clear_pixmap(a->pix, 0 ,0, a->width, a->height);
153 XCopyArea (server.dsp, ((Panel *)a->panel)->temp_pmap, a->pix, server.gc, a->posx, a->posy, a->width, a->height, 0, 0);
154
155 cairo_surface_t *cs;
156 cairo_t *c;
157
158 cs = cairo_xlib_surface_create (server.dsp, a->pix, server.visual, a->width, a->height);
159 c = cairo_create (cs);
160
161 draw_background (a, c);
162
163 if (a->_draw_foreground)
164 a->_draw_foreground(a, c);
165
166 cairo_destroy (c);
167 cairo_surface_destroy (cs);
168 }
169
170
171 void draw_background (Area *a, cairo_t *c)
172 {
173 if (a->bg->back.alpha > 0.0) {
174 //printf(" draw_background (%d %d) RGBA (%lf, %lf, %lf, %lf)\n", a->posx, a->posy, pix->back.color[0], pix->back.color[1], pix->back.color[2], pix->back.alpha);
175 draw_rect(c, a->bg->border.width, a->bg->border.width, a->width-(2.0 * a->bg->border.width), a->height-(2.0*a->bg->border.width), a->bg->border.rounded - a->bg->border.width/1.571);
176 cairo_set_source_rgba(c, a->bg->back.color[0], a->bg->back.color[1], a->bg->back.color[2], a->bg->back.alpha);
177 cairo_fill(c);
178 }
179
180 if (a->bg->border.width > 0 && a->bg->border.alpha > 0.0) {
181 cairo_set_line_width (c, a->bg->border.width);
182
183 // draw border inside (x, y, width, height)
184 draw_rect(c, a->bg->border.width/2.0, a->bg->border.width/2.0, a->width - a->bg->border.width, a->height - a->bg->border.width, a->bg->border.rounded);
185 /*
186 // convert : radian = degre * M_PI/180
187 // definir le degrade dans un carre de (0,0) (100,100)
188 // ensuite ce degrade est extrapoler selon le ratio width/height
189 // dans repere (0, 0) (100, 100)
190 double X0, Y0, X1, Y1, degre;
191 // x = X * (a->width / 100), y = Y * (a->height / 100)
192 double x0, y0, x1, y1;
193 X0 = 0;
194 Y0 = 100;
195 X1 = 100;
196 Y1 = 0;
197 degre = 45;
198 // et ensuite faire la changement d'unite du repere
199 // car ce qui doit reste inchangee est les traits et pas la direction
200
201 // il faut d'abord appliquer une rotation de 90 (et -180 si l'angle est superieur a 180)
202 // ceci peut etre applique une fois pour toute au depart
203 // ensuite calculer l'angle dans le nouveau repare
204 // puis faire une rotation de 90
205 x0 = X0 * ((double)a->width / 100);
206 x1 = X1 * ((double)a->width / 100);
207 y0 = Y0 * ((double)a->height / 100);
208 y1 = Y1 * ((double)a->height / 100);
209
210 x0 = X0 * ((double)a->height / 100);
211 x1 = X1 * ((double)a->height / 100);
212 y0 = Y0 * ((double)a->width / 100);
213 y1 = Y1 * ((double)a->width / 100);
214
215 cairo_pattern_t *linpat;
216 linpat = cairo_pattern_create_linear (x0, y0, x1, y1);
217 cairo_pattern_add_color_stop_rgba (linpat, 0, a->border.color[0], a->border.color[1], a->border.color[2], a->border.alpha);
218 cairo_pattern_add_color_stop_rgba (linpat, 1, a->border.color[0], a->border.color[1], a->border.color[2], 0);
219 cairo_set_source (c, linpat);
220 */
221 cairo_set_source_rgba (c, a->bg->border.color[0], a->bg->border.color[1], a->bg->border.color[2], a->bg->border.alpha);
222
223 cairo_stroke (c);
224 //cairo_pattern_destroy (linpat);
225 }
226 }
227
228
229 void remove_area (Area *a)
230 {
231 Area *parent = (Area*)a->parent;
232
233 parent->list = g_slist_remove(parent->list, a);
234 set_redraw (parent);
235
236 }
237
238
239 void add_area (Area *a)
240 {
241 Area *parent = (Area*)a->parent;
242
243 parent->list = g_slist_remove(parent->list, a);
244 set_redraw (parent);
245
246 }
247
248
249 void free_area (Area *a)
250 {
251 GSList *l0;
252 for (l0 = a->list; l0 ; l0 = l0->next)
253 free_area (l0->data);
254
255 if (a->list) {
256 g_slist_free(a->list);
257 a->list = 0;
258 }
259 if (a->pix) {
260 XFreePixmap (server.dsp, a->pix);
261 a->pix = 0;
262 }
263 }
264
265
266 void draw_rect(cairo_t *c, double x, double y, double w, double h, double r)
267 {
268 if (r > 0.0) {
269 double c1 = 0.55228475 * r;
270
271 cairo_move_to(c, x+r, y);
272 cairo_rel_line_to(c, w-2*r, 0);
273 cairo_rel_curve_to(c, c1, 0.0, r, c1, r, r);
274 cairo_rel_line_to(c, 0, h-2*r);
275 cairo_rel_curve_to(c, 0.0, c1, c1-r, r, -r, r);
276 cairo_rel_line_to (c, -w +2*r, 0);
277 cairo_rel_curve_to (c, -c1, 0, -r, -c1, -r, -r);
278 cairo_rel_line_to (c, 0, -h + 2 * r);
279 cairo_rel_curve_to (c, 0, -c1, r - c1, -r, r, -r);
280 }
281 else
282 cairo_rectangle(c, x, y, w, h);
283 }
284
285
286 void clear_pixmap(Pixmap p, int x, int y, int w, int h)
287 {
288 Picture pict = XRenderCreatePicture(server.dsp, p, XRenderFindVisualFormat(server.dsp, server.visual), 0, 0);
289 XRenderColor col = { .red=0, .green=0, .blue=0, .alpha=0 };
290 XRenderFillRectangle(server.dsp, PictOpSrc, pict, &col, x, y, w, h);
291 XRenderFreePicture(server.dsp, pict);
292 }
This page took 0.054349 seconds and 5 git commands to generate.