1 /* -*- Mode: C++-C -*-
2 *
3 * Copyright 1994 Christopher B. Liebman
4 *
5 * Permission to use, copy, modify, distribute, and sell this software
6 * and its documentation for any purpose is hereby granted without fee,
7 * provided that the above copyright notice appear in all copies and that
8 * both that copyright notice and this permission notice appear in
9 * supporting documentation, and that the name Christopher B. Liebman not
10 * be used in advertising or publicity pertaining to distribution of this
11 * software without specific, written prior permission.
12 *
13 * THIS SOFTWARE IS PROVIDED `AS-IS'. CHRISTOPHER B. LIEBMAN, DISCLAIMS
14 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
15 * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL CHRISTOPHER
17 * B. LIEBMAN, BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING SPECIAL,
18 * INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, OR
19 * PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
20 * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF
21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Author : Chris Liebman
24 * Created On : Tue Jan 11 14:11:30 1994
25 * Last Modified By: Chris Liebman
26 * Last Modified On: Sun Feb 13 17:10:53 1994
27 * Update Count : 30
28 * Status : Released
29 *
30 * HISTORY
31 * 13-Feb-1994 Chris Liebman
32 * Last Modified: Tue Feb 1 08:14:16 1994 #29 (Chris Liebman)
33 * Use shape pixmap from face if available.
34 *
35 * 1-Feb-1994 Chris Liebman
36 * Last Modified: Mon Jan 31 23:07:23 1994 #24 (Chris Liebman)
37 * Added a hack to handle the case where the mask (an the image pixmap
38 * are smaller than the widget. In this case the Label widget centers
39 * the image so we attempt to center the shape mask.
40 *
41 * 31-Jan-1994 Chris Liebman
42 * Last Modified: Mon Jan 31 23:05:49 1994 #21 (Chris Liebman)
43 * More shape support improvements.
44 *
45 * 24-Jan-1994 Chris Liebman
46 * Last Modified: Sun Jan 23 17:40:55 1994 #12 (Chris Liebman)
47 * Much improved shape support.
48 *
49 * PURPOSE
50 * Shape the faces window to the combined image masks.
51 */
52
53 #ifndef lint
54 static char *RCSid = "$Id: face_shape.c,v 1.10 1994/02/13 22:33:30 liebman Exp $";
55 #endif
56
57 #include "faces.h"
58 #include <X11/extensions/shape.h>
59
60 static Boolean initialized = False;
61 static GC FaceShapeGC;
62 static Pixmap FaceShapePixmap;
63
64 static void
FaceShapeFace(widget,shape)65 FaceShapeFace(widget, shape)
66 Widget widget;
67 Pixmap shape;
68 {
69 Dimension width = 0;
70 Dimension height = 0;
71 Dimension borderWidth;
72 Dimension internalWidth;
73 Dimension internalHeight;
74 Position x;
75 Position y;
76 int maskX;
77 int maskY;
78 Window child;
79
80 /*
81 * Get the origin of this widget.
82 */
83
84 XtVaGetValues(widget, XtNx, &x, XtNy, &y,
85 XtNwidth, &width, XtNheight, &height,
86 XtNborderWidth, &borderWidth,
87 XtNinternalHeight, &internalHeight,
88 XtNinternalWidth, &internalWidth,
89 NULL);
90
91 /*
92 * If we have no shape then we shape the window to inside the borders
93 * or to inside the internal width and height.
94 */
95
96 if (shape == None)
97 {
98 if (TheFacesResources.shape_borders)
99 {
100 x += borderWidth;
101 y += borderWidth;
102
103 if (TheFacesResources.shape_internal)
104 {
105 x += internalWidth;
106 y += internalHeight;
107 width -= 2 * internalWidth;
108 height -= 2 * internalHeight;
109 }
110 }
111 else
112 {
113 x -= borderWidth;
114 y -= borderWidth;
115 width += 2 * borderWidth;
116 height += 2 * borderWidth;
117 }
118 }
119 else
120 {
121 x += borderWidth;
122 y += borderWidth;
123 }
124
125 /*
126 * Now convert to choords in terms of the top level shell
127 * window.
128 */
129
130 XTranslateCoordinates(XtDisplay(TheTopLevel), XtWindow(TheFrame),
131 XtWindow(TheTopLevel), x, y, &maskX, &maskY,
132 &child);
133
134 /*
135 * If this widget has a shape then apply it.
136 * Otherwise set use the size info to set the shape mask.
137 */
138
139 if (shape != None)
140 {
141 /*
142 * We need this bit of code until we have a real "tiled" widget
143 * as the frame.
144 */
145
146 Window junkroot;
147 int junkx, junky;
148 unsigned int junkbw, junkdepth;
149 unsigned int shapeWidth;
150 unsigned int shapeHeight;
151 int width_diff, height_diff;
152
153 XGetGeometry(XtDisplay(TheTopLevel), shape,
154 &junkroot, &junkx, &junky,
155 &shapeWidth, &shapeHeight,
156 &junkbw, &junkdepth);
157
158 width_diff = width - shapeWidth;
159 height_diff = height - shapeHeight;
160
161 /*
162 * Note: We only adjust when the widget width is greater than the
163 * shape width!
164 */
165
166 if (width_diff > 0)
167 {
168 maskX += width_diff / 2;
169 width = shapeWidth;
170 }
171
172 if (height_diff > 0)
173 {
174 maskY += height_diff / 2;
175 height = shapeHeight;
176 }
177
178 /*
179 * Copy in this part of the shape.
180 */
181
182 XCopyArea(XtDisplay(TheTopLevel), shape, FaceShapePixmap,
183 FaceShapeGC,
184 0, 0, width, height,
185 maskX, maskY);
186 }
187 else
188 {
189 XFillRectangle(XtDisplay(TheTopLevel), FaceShapePixmap,
190 FaceShapeGC, maskX, maskY, width, height);
191 }
192 }
193
194 void
FaceShapeCreate()195 FaceShapeCreate()
196 {
197 Dimension width = 0;
198 Dimension height = 0;
199 XGCValues values;
200 Face *face;
201 XWindowAttributes attributes;
202
203 if (TheFacesResources.use_shape != True)
204 {
205 return;
206 }
207
208 if (FaceShapePixmap != None)
209 {
210 XFreePixmap(XtDisplay(TheFrame), FaceShapePixmap);
211 FaceShapePixmap = None;
212 }
213
214 /*
215 * We have to get the window attributes as a get values will still get
216 * old information untill we start processing events!
217 */
218
219 XGetWindowAttributes(XtDisplay(TheTopLevel), XtWindow(TheTopLevel),
220 &attributes);
221 width = attributes.width;
222 height = attributes.height;
223
224 FaceShapePixmap = XCreatePixmap(XtDisplay(TheTopLevel),
225 XtWindow(TheTopLevel),
226 width, height, 1);
227
228 /*
229 * If we have not done it yet, create a graphic context.
230 */
231
232 if (initialized != True)
233 {
234 FaceShapeGC = XCreateGC(XtDisplay(TheTopLevel), FaceShapePixmap,
235 0, &values);
236 initialized = True;
237 }
238
239 /*
240 * Set shape mask to all zeros.
241 */
242
243 XSetForeground(XtDisplay(TheTopLevel), FaceShapeGC, 0);
244 XFillRectangle(XtDisplay(TheTopLevel), FaceShapePixmap, FaceShapeGC,
245 0, 0, width, height);
246
247 /*
248 * Now we will use ones to shape the window.
249 */
250
251 XSetForeground(XtDisplay(TheTopLevel), FaceShapeGC, 1);
252
253 /*
254 * Now go thru the face list and apply any shape masks.
255 */
256
257 for (face = TheFaceList; face != NULL; face = face->next)
258 {
259 FaceShapeFace(face->widget, face->shape);
260 }
261
262 /*
263 * If there are no faces in the list then set the shape mask
264 * to all ones.
265 */
266
267 if (TheFaceList == NULL)
268 {
269 FaceShapeFace(NoMailWidget, FaceImageShape(NoMailImage));
270 }
271
272 /*
273 * Ok, now shape the window, I hope!
274 */
275
276 XShapeCombineMask(XtDisplay(TheTopLevel), XtWindow(TheTopLevel),
277 ShapeBounding, 0, 0, FaceShapePixmap, ShapeSet);
278 }
279
280