1 /* $Id: shape.c,v 1.1 1999/08/19 00:55:43 jtg Exp $ */
4 * Example of using the X "shape" extension with OpenGL: render a spinning
5 * cube inside of a non-rectangular window.
7 * Press ESC to exit. Press up/down to change window shape.
9 * To compile add "shape" to the PROGS list in Makefile.
14 * This program is in the public domain.
22 #include <X11/Xutil.h>
23 #include <X11/keysym.h>
24 #include <X11/extensions/shape.h>
32 static int Width
=500, Height
=500;
34 static float Xangle
= 0.0, Yangle
= 0.0;
35 static int Redraw
= 0;
37 static int MinSides
= 3;
38 static int MaxSides
= 20;
42 * Draw the OpenGL stuff and do a SwapBuffers.
44 static void display(Display
*dpy
, Window win
)
48 glClear(GL_COLOR_BUFFER_BIT
);
52 glScalef(scale
, scale
, scale
);
53 glRotatef(Xangle
, 1.0, 0.0, 0.0);
54 glRotatef(Yangle
, 0.0, 1.0, 0.0);
56 glColor3f(1.0, 1.0, 1.0);
57 glBegin(GL_LINE_LOOP
);
58 glVertex3f(-1.0, -1.0, -1.0);
59 glVertex3f( 1.0, -1.0, -1.0);
60 glVertex3f( 1.0, 1.0, -1.0);
61 glVertex3f(-1.0, 1.0, -1.0);
64 glBegin(GL_LINE_LOOP
);
65 glVertex3f(-1.0, -1.0, 1.0);
66 glVertex3f( 1.0, -1.0, 1.0);
67 glVertex3f( 1.0, 1.0, 1.0);
68 glVertex3f(-1.0, 1.0, 1.0);
72 glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, 1.0);
73 glVertex3f( 1.0, -1.0, -1.0); glVertex3f( 1.0, -1.0, 1.0);
74 glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, 1.0, 1.0);
75 glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0);
80 glXSwapBuffers(dpy
, win
);
85 * Called when no events are pending.
87 static void idle(void)
96 * This is called when we have to recompute the window shape bitmask.
97 * We just generate an n-sided regular polygon here but any other shape
100 static void make_shape_mask(Display
*dpy
, Window win
, int width
, int height
,
107 /* allocate 1-bit deep pixmap and a GC */
108 shapeMask
= XCreatePixmap(dpy
, win
, width
, height
, 1);
109 gc
= XCreateGC(dpy
, shapeMask
, 0, &xgcv
);
111 /* clear shapeMask to zeros */
112 XSetForeground(dpy
, gc
, 0);
113 XFillRectangle(dpy
, shapeMask
, gc
, 0, 0, width
, height
);
116 XSetForeground(dpy
, gc
, 1);
121 float step
= 2.0 * PI
/ sides
;
122 float radius
= width
/ 2;
125 for (i
=0;i
<sides
;i
++) {
126 int x
= cx
+ radius
* sin(angle
);
127 int y
= cy
- radius
* cos(angle
);
132 XFillPolygon(dpy
, shapeMask
, gc
, points
, sides
, Convex
, CoordModeOrigin
);
135 /* This is the only SHAPE extension call- simple! */
136 XShapeCombineMask(dpy
, win
, ShapeBounding
, 0, 0, shapeMask
, ShapeSet
);
139 XFreePixmap(dpy
, shapeMask
);
144 * Called when window is resized. Do OpenGL viewport and projection stuff.
146 static void reshape(int width
, int height
)
148 glViewport(0, 0, width
, height
);
149 glMatrixMode(GL_PROJECTION
);
151 glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 20.0);
152 glMatrixMode(GL_MODELVIEW
);
154 glTranslatef(0.0, 0.0, -10.0);
161 static void event_loop(Display
*dpy
, Window win
)
166 XNextEvent(dpy
, &event
);
167 switch (event
.type
) {
169 display(dpy
, event
.xexpose
.window
);
171 case ConfigureNotify
:
172 Width
= event
.xconfigure
.width
;
173 Height
= event
.xconfigure
.height
,
174 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
175 reshape(Width
, Height
);
182 XLookupString(&event
.xkey
, buf
, sizeof(buf
), &keySym
, &stat
);
189 if (Sides
>MaxSides
) Sides
= MaxSides
;
190 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
194 if (Sides
<MinSides
) Sides
= MinSides
;
195 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
216 * Allocate a "nice" colormap. This could be better (HP-CR support, etc).
218 static Colormap
alloc_colormap(Display
*dpy
, Window parent
, Visual
*vis
)
220 Screen
*scr
= DefaultScreenOfDisplay(dpy
);
221 int scrnum
= DefaultScreen(dpy
);
223 if (MaxCmapsOfScreen(scr
)==1 && vis
==DefaultVisual(dpy
, scrnum
)) {
224 /* The window and root are of the same visual type so */
225 /* share the root colormap. */
226 return DefaultColormap(dpy
, scrnum
);
229 return XCreateColormap(dpy
, parent
, vis
, AllocNone
);
234 int main(int argc
, char *argv
[])
236 static int glAttribs
[] = {
243 XVisualInfo
*visInfo
;
248 XSetWindowAttributes winAttribs
;
249 unsigned long winAttribsMask
;
253 dpy
= XOpenDisplay(NULL
);
255 fprintf(stderr
, "Couldn't open default display\n");
259 /* check that we can use the shape extension */
260 if (!XQueryExtension(dpy
, "SHAPE", &ignore
, &ignore
, &ignore
)) {
261 fprintf(stderr
, "Display doesn't support shape extension\n");
265 scrn
= DefaultScreen(dpy
);
267 root
= RootWindow(dpy
, scrn
);
269 visInfo
= glXChooseVisual(dpy
, scrn
, glAttribs
);
271 fprintf(stderr
, "Couldn't get RGB, DB, Z visual\n");
275 glCtx
= glXCreateContext(dpy
, visInfo
, 0, True
);
277 fprintf(stderr
, "Couldn't create GL context\n");
281 cmap
= alloc_colormap(dpy
, root
, visInfo
->visual
);
283 fprintf(stderr
, "Couln't create colormap\n");
287 winAttribs
.border_pixel
= 0;
288 winAttribs
.colormap
= cmap
;
289 winAttribs
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
290 winAttribsMask
= CWBorderPixel
| CWColormap
| CWEventMask
;
291 win
= XCreateWindow(dpy
, root
, 0, 0, Width
, Height
, 0,
292 visInfo
->depth
, InputOutput
,
294 winAttribsMask
, &winAttribs
);
295 XMapWindow(dpy
, win
);
297 glXMakeCurrent(dpy
, win
, glCtx
);
299 printf("Press ESC to exit.\n");
300 printf("Press up/down to change window shape.\n");
302 event_loop(dpy
, win
);