]> icculus.org git repositories - dana/openbox.git/blob - render2/surface.c
better math to find the area in teh child to update
[dana/openbox.git] / render2 / surface.c
1 #include "surface.h"
2 #include "instance.h"
3 #include <assert.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 /* doesn't set win or parent */
8 static struct RrSurface *surface_new(enum RrSurfaceType type,
9                                      int numtex)
10 {
11     struct RrSurface *sur;
12
13     sur = malloc(sizeof(struct RrSurface));
14     sur->type = type;
15     sur->ntextures = numtex;
16     if (numtex) {
17         sur->texture = malloc(sizeof(struct RrTexture) * numtex);
18         memset(sur->texture, 0, sizeof(struct RrTexture) * numtex);
19     } else
20         sur->texture = NULL;
21     sur->x = 0;
22     sur->y = 0;
23     sur->w = 1;
24     sur->h = 1;
25     sur->visible = 0;
26     sur->children = NULL;
27     return sur;
28 }
29
30 static Window create_window(struct RrInstance *inst, Window parent)
31 {
32     XSetWindowAttributes attrib;
33     Window win;
34
35     attrib.event_mask = ExposureMask;
36     win = XCreateWindow(RrDisplay(inst), parent, 0, 0, 1, 1, 0,
37                         RrDepth(inst), InputOutput, RrVisual(inst),
38                         CWEventMask, &attrib);
39     return win;
40 }
41
42 struct RrSurface *RrSurfaceNewProto(enum RrSurfaceType type,
43                                     int numtex)
44 {
45     struct RrSurface *sur;
46
47     sur = surface_new(type, numtex);
48     sur->inst = NULL;
49     sur->win = None;
50     sur->parent = NULL;
51     sur->visible = 0;
52     return sur;
53 }
54
55 struct RrSurface *RrSurfaceNew(struct RrInstance *inst,
56                                enum RrSurfaceType type,
57                                Window win,
58                                int numtex)
59 {
60     struct RrSurface *sur;
61
62     sur = surface_new(type, numtex);
63     sur->inst = inst;
64     sur->win = win;
65     sur->parent = NULL;
66     sur->visible = 0;
67
68     RrInstaceAddSurface(sur);
69     return sur;
70 }
71
72 struct RrSurface *RrSurfaceNewChild(enum RrSurfaceType type,
73                                     struct RrSurface *parent,
74                                     int numtex)
75 {
76     struct RrSurface *sur;
77
78     /* can't be a child of a prototype! */
79     assert(parent->inst);
80     if (!parent->inst) return NULL;
81
82     sur = surface_new(type, numtex);
83     sur->inst = parent->inst;
84     sur->win = create_window(sur->inst, parent->win);
85     sur->parent = parent;
86     RrSurfaceShow(sur);
87
88     parent->children = g_slist_append(parent->children, sur);
89
90     RrInstaceAddSurface(sur);
91     return sur;
92 }
93
94 /* doesn't set win or parent */
95 static struct RrSurface *surface_copy(struct RrSurface *orig)
96 {
97     struct RrSurface *sur;
98
99     sur = malloc(sizeof(struct RrSurface));
100     sur->type = orig->type;
101     switch (sur->type) {
102     case RR_SURFACE_PLANAR:
103         sur->data = orig->data;
104         break;
105     case RR_SURFACE_NONPLANAR:
106         assert(0);
107         break;
108     case RR_SURFACE_NONE:
109         break;
110     }
111     sur->ntextures = orig->ntextures;
112     sur->texture = malloc(sizeof(struct RrTexture) * sur->ntextures);
113     memcpy(sur->texture, orig->texture,
114            sizeof(struct RrTexture) * sur->ntextures);
115     return sur;
116 }
117
118 struct RrSurface *RrSurfaceCopy(struct RrInstance *inst,
119                                 struct RrSurface *orig,
120                                 Window win)
121 {
122     struct RrSurface *sur;
123
124     sur = surface_copy(orig);
125     sur->inst = inst;
126     sur->win = win;
127     sur->parent = NULL;
128     sur->visible = 0;
129
130     RrInstaceAddSurface(sur);
131     return sur;
132 }
133
134 struct RrSurface *RrSurfaceCopyChild(struct RrSurface *orig,
135                                      struct RrSurface *parent)
136 {
137     struct RrSurface *sur;
138
139     /* can't be a child of a prototype! */
140     assert(parent->inst);
141     if (!parent->inst) return NULL;
142
143     sur = surface_copy(orig);
144     sur->inst = parent->inst;
145     sur->win = create_window(sur->inst, parent->win);
146     sur->parent = parent;
147     RrSurfaceShow(sur);
148
149     parent->children = g_slist_append(parent->children, sur);
150
151     RrInstaceAddSurface(sur);
152     return sur;
153 }
154
155 void RrSurfaceFree(struct RrSurface *sur)
156 {
157     int i;
158     if (sur) {
159         if (sur->parent)
160             sur->parent->children = g_slist_remove(sur->parent->children, sur);
161
162         RrInstaceRemoveSurface(sur);
163         for (i = 0; i < sur->ntextures; ++i)
164             RrTextureFreeContents(&sur->texture[i]);
165         if (sur->ntextures)
166             free(sur->texture);
167         if (sur->parent && sur->win)
168             XDestroyWindow(RrDisplay(sur->inst), sur->win);
169         free(sur);
170     }
171 }
172
173 void RrSurfaceSetArea(struct RrSurface *sur,
174                       int x,
175                       int y,
176                       int w,
177                       int h)
178 {
179     assert(w > 0 && h > 0);
180     if (!(w > 0 && h > 0)) return;
181
182     sur->x = x;
183     sur->y = y;
184     sur->w = w;
185     sur->h = h;
186     if (sur->win)
187         XMoveResizeWindow(RrDisplay(sur->inst), sur->win, x, y, w, h);
188 }
189
190 Window RrSurfaceWindow(struct RrSurface *sur)
191 {
192     /* can't get a window for a prototype */
193     assert(sur->inst);
194     if (!sur->inst) return None;
195
196     return sur->win;
197 }
198
199 struct RrTexture *RrSurfaceTexture(struct RrSurface *sur, int texnum)
200 {
201     assert(texnum < sur->ntextures);
202     return &(sur->texture[texnum]);
203 }
204
205 void RrSurfaceMinSize(struct RrSurface *sur, int *w, int *h)
206 {
207     int i;
208     int minw, minh;
209
210     switch(sur->type) {
211     case RR_SURFACE_NONE:
212         *w = *h = 0;
213         break;
214     case RR_SURFACE_PLANAR:
215         RrPlanarMinSize(sur, w, h);
216         break;
217     case RR_SURFACE_NONPLANAR:
218         assert(0);
219         break;
220     }
221
222     minw = minh = 0;
223     for (i = 0; i < sur->ntextures; ++i) {
224         switch (sur->texture[i].type) {
225         case RR_TEXTURE_NONE:
226             minw = MAX(minw, 0);
227             minh = MAX(minh, 0);
228             break;
229         case RR_TEXTURE_TEXT:
230             /* XXX MEASUER STRING PLS */
231             minw = MAX(minw, 100 /*MEASURESTRING*/); 
232             minh = MAX(minh, 10  /*HEIGHTOFFONT*/);
233             break;
234         case RR_TEXTURE_RGBA:
235             minw = MAX(minw, (sur->texture[i].data.rgba.x +
236                               sur->texture[i].data.rgba.w));
237             minh = MAX(minw, (sur->texture[i].data.rgba.y +
238                               sur->texture[i].data.rgba.h));
239             break;
240         }
241     }
242
243     *w += minw;
244     *h += minh;
245     /* zeros are bad. */
246     if (*w == 0) *w = 1;
247     if (*h == 0) *h = 1;
248 }
249
250 void RrSurfaceShow(struct RrSurface *sur)
251 {
252     sur->visible = 1;
253     if (sur->win)
254         XMapWindow(RrDisplay(sur->inst), sur->win);
255 }
256
257 void RrSurfaceHide(struct RrSurface *sur)
258 {
259     sur->visible = 0;
260     if (sur->win)
261         XUnmapWindow(RrDisplay(sur->inst), sur->win);
262 }
263
264 int RrSurfaceVisible(struct RrSurface *sur)
265 {
266     return sur->visible;
267 }