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