]> icculus.org git repositories - dana/openbox.git/blob - render2/surface.c
the kernel is using th gl shit to render itself, but with the old style frame shit...
[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 #ifdef    SHAPE
7 #include <X11/extensions/shape.h>
8 #endif
9
10 /* doesn't set win or parent */
11 static struct RrSurface *surface_new(enum RrSurfaceType type,
12                                      int numtex)
13 {
14     struct RrSurface *sur;
15
16     sur = malloc(sizeof(struct RrSurface));
17     sur->type = type;
18     sur->shape_base = None;
19     sur->shape_base_x = 0;
20     sur->shape_base_y = 0;
21     sur->ntextures = numtex;
22     if (numtex) {
23         sur->texture = malloc(sizeof(struct RrTexture) * numtex);
24         memset(sur->texture, 0, sizeof(struct RrTexture) * numtex);
25     } else
26         sur->texture = NULL;
27     sur->x = 0;
28     sur->y = 0;
29     sur->w = 1;
30     sur->h = 1;
31     sur->visible = 0;
32     sur->children = NULL;
33     return sur;
34 }
35
36 static Window create_window(struct RrInstance *inst, Window parent)
37 {
38     XSetWindowAttributes attrib;
39     Window win;
40
41     attrib.event_mask = ExposureMask;
42     win = XCreateWindow(RrDisplay(inst), parent, 0, 0, 1, 1, 0,
43                         RrDepth(inst), InputOutput, RrVisual(inst),
44                         CWEventMask, &attrib);
45     return win;
46 }
47
48 struct RrSurface *RrSurfaceNewProto(enum RrSurfaceType type,
49                                     int numtex)
50 {
51     struct RrSurface *sur;
52
53     sur = surface_new(type, numtex);
54     sur->inst = NULL;
55     sur->win = None;
56     sur->parent = NULL;
57     sur->visible = 0;
58     return sur;
59 }
60
61 struct RrSurface *RrSurfaceNew(struct RrInstance *inst,
62                                enum RrSurfaceType type,
63                                Window win,
64                                int numtex)
65 {
66     struct RrSurface *sur;
67
68     sur = surface_new(type, numtex);
69     sur->inst = inst;
70     sur->win = win;
71     sur->parent = NULL;
72     sur->visible = 0;
73
74     RrInstaceAddSurface(sur);
75     return sur;
76 }
77
78 struct RrSurface *RrSurfaceNewChild(enum RrSurfaceType type,
79                                     struct RrSurface *parent,
80                                     int numtex)
81 {
82     struct RrSurface *sur;
83
84     /* can't be a child of a prototype! */
85     assert(parent->inst);
86     if (!parent->inst) return NULL;
87
88     sur = surface_new(type, numtex);
89     sur->inst = parent->inst;
90     sur->win = create_window(sur->inst, parent->win);
91     sur->parent = parent;
92     RrSurfaceShow(sur);
93
94     parent->children = g_slist_append(parent->children, sur);
95
96     RrInstaceAddSurface(sur);
97     return sur;
98 }
99
100 void RrSurfaceCopy(struct RrSurface *dest, struct RrSurface *src)
101 {
102     dest->type = src->type;
103     switch (dest->type) {
104     case RR_SURFACE_PLANAR:
105         dest->data = src->data;
106         break;
107     case RR_SURFACE_NONPLANAR:
108         assert(0);
109         break;
110     case RR_SURFACE_NONE:
111         break;
112     }
113     free(dest->texture);
114     dest->ntextures = src->ntextures;
115     dest->texture = malloc(sizeof(struct RrTexture) * dest->ntextures);
116     memcpy(dest->texture, src->texture,
117            sizeof(struct RrTexture) * dest->ntextures);
118 }
119
120 void RrSurfaceFree(struct RrSurface *sur)
121 {
122     int i;
123     if (sur) {
124         if (sur->parent)
125             sur->parent->children = g_slist_remove(sur->parent->children, sur);
126
127         RrInstaceRemoveSurface(sur);
128         for (i = 0; i < sur->ntextures; ++i)
129             RrTextureFreeContents(&sur->texture[i]);
130         if (sur->ntextures)
131             free(sur->texture);
132         if (sur->parent && sur->win)
133             XDestroyWindow(RrDisplay(sur->inst), sur->win);
134         free(sur);
135     }
136 }
137
138 void RrSurfaceSetPos(struct RrSurface *sur,
139                      int x,
140                      int y)
141 {
142     RrSurfaceSetArea(sur, x, y, sur->w, sur->h);
143 }
144
145 void RrSurfaceSetSize(struct RrSurface *sur,
146                       int w,
147                       int h)
148 {
149     RrSurfaceSetArea(sur, sur->x, sur->y, w, h);
150 }
151
152 void RrSurfaceSetArea(struct RrSurface *sur,
153                       int x,
154                       int y,
155                       int w,
156                       int h)
157 {
158     assert(w > 0 && h > 0);
159     if (!(w > 0 && h > 0)) return;
160
161     sur->x = x;
162     sur->y = y;
163     sur->w = w;
164     sur->h = h;
165     if (sur->win)
166         XMoveResizeWindow(RrDisplay(sur->inst), sur->win, x, y, w, h);
167 }
168
169 Window RrSurfaceWindow(struct RrSurface *sur)
170 {
171     /* can't get a window for a prototype */
172     assert(sur->inst);
173     if (!sur->inst) return None;
174
175     return sur->win;
176 }
177
178 struct RrTexture *RrSurfaceTexture(struct RrSurface *sur, int texnum)
179 {
180     assert(texnum < sur->ntextures);
181     return &(sur->texture[texnum]);
182 }
183
184 void RrSurfaceMinSize(struct RrSurface *sur, int *w, int *h)
185 {
186     int i;
187     int minw, minh;
188
189     switch(sur->type) {
190     case RR_SURFACE_NONE:
191         *w = *h = 0;
192         break;
193     case RR_SURFACE_PLANAR:
194         RrPlanarMinSize(sur, w, h);
195         break;
196     case RR_SURFACE_NONPLANAR:
197         assert(0);
198         break;
199     }
200
201     minw = minh = 0;
202     for (i = 0; i < sur->ntextures; ++i) {
203         switch (sur->texture[i].type) {
204         case RR_TEXTURE_NONE:
205             minw = MAX(minw, 0);
206             minh = MAX(minh, 0);
207             break;
208         case RR_TEXTURE_TEXT:
209             /* XXX MEASUER STRING PLS */
210             minw = MAX(minw, 100 /*MEASURESTRING*/); 
211             minh = MAX(minh, 10  /*HEIGHTOFFONT*/);
212             break;
213         case RR_TEXTURE_RGBA:
214             minw = MAX(minw, (sur->texture[i].data.rgba.x +
215                               sur->texture[i].data.rgba.w));
216             minh = MAX(minw, (sur->texture[i].data.rgba.y +
217                               sur->texture[i].data.rgba.h));
218             break;
219         }
220     }
221
222     *w += minw;
223     *h += minh;
224     /* zeros are bad. */
225     if (*w == 0) *w = 1;
226     if (*h == 0) *h = 1;
227 }
228
229 void RrSurfaceShow(struct RrSurface *sur)
230 {
231     sur->visible = 1;
232     if (sur->win)
233         XMapWindow(RrDisplay(sur->inst), sur->win);
234 }
235
236 void RrSurfaceHide(struct RrSurface *sur)
237 {
238     sur->visible = 0;
239     if (sur->win)
240         XUnmapWindow(RrDisplay(sur->inst), sur->win);
241 }
242
243 int RrSurfaceVisible(struct RrSurface *sur)
244 {
245     assert(sur->inst);
246     return sur->visible;
247 }
248
249 void RrSurfaceShapeSetBase(struct RrSurface *sur, Window base, int x, int y)
250 {
251     assert(sur->inst);
252     sur->shape_base = base;
253     sur->shape_base_x = x;
254     sur->shape_base_y = y;
255 }
256
257 void RrSurfaceShape(struct RrSurface *sur)
258 {
259     GSList *it;
260
261     assert(sur->inst);
262
263 #ifdef SHAPE
264     XResizeWindow(RrDisplay(sur->inst), RrShapeWindow(sur->inst),
265                   sur->w, sur->h);
266     XShapeCombineShape(RrDisplay(sur->inst), RrShapeWindow(sur->inst),
267                        ShapeBounding,
268                        sur->shape_base_x, sur->shape_base_y,
269                        sur->shape_base, ShapeBounding, ShapeSet);
270     /* include the shape of the children */
271     for (it = sur->children; it; it = g_slist_next(it)) {
272         struct RrSurface *ch = it->data;
273         if (ch->win)
274             XShapeCombineShape(RrDisplay(sur->inst),
275                                RrShapeWindow(sur->inst),
276                                ShapeBounding, ch->x, ch->y, ch->win,
277                                ShapeBounding, ShapeUnion);
278     }
279     switch (sur->type) {
280     case RR_SURFACE_NONE:
281         break;
282     case RR_SURFACE_PLANAR:
283         /* XXX shape me based on something! an alpha mask? */
284         break;
285     case RR_SURFACE_NONPLANAR:
286         /* XXX shape me based on my GL form! */
287         assert(0);
288         break;
289     }
290
291     /* apply the final shape */
292     XShapeCombineShape(RrDisplay(sur->inst), sur->win, ShapeBounding, 0, 0,
293                        RrShapeWindow(sur->inst), ShapeBounding, ShapeSet);
294 #endif
295 }