1 /*
2  *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3  *
4  *Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  *"Software"), to deal in the Software without restriction, including
7  *without limitation the rights to use, copy, modify, merge, publish,
8  *distribute, sublicense, and/or sell copies of the Software, and to
9  *permit persons to whom the Software is furnished to do so, subject to
10  *the following conditions:
11  *
12  *The above copyright notice and this permission notice shall be
13  *included in all copies or substantial portions of the Software.
14  *
15  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19  *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20  *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21  *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  *Except as contained in this notice, the name of the XFree86 Project
24  *shall not be used in advertising or otherwise to promote the sale, use
25  *or other dealings in this Software without prior written authorization
26  *from the XFree86 Project.
27  *
28  * Authors:	Harold L Hunt II
29  *		Kensuke Matsuzaki
30  */
31 
32 #ifdef HAVE_XWIN_CONFIG_H
33 #include <xwin-config.h>
34 #endif
35 #include "win.h"
36 
37 /*
38  * Prototypes for local functions
39  */
40 
41 static int
42  winAddRgn(WindowPtr pWindow, void *data);
43 
44 static
45     void
46  winUpdateRgnRootless(WindowPtr pWindow);
47 
48 static
49     void
50  winReshapeRootless(WindowPtr pWin);
51 
52 /* See Porting Layer Definition - p. 37 */
53 /* See mfb/mfbwindow.c - mfbCreateWindow() */
54 
55 Bool
winCreateWindowRootless(WindowPtr pWin)56 winCreateWindowRootless(WindowPtr pWin)
57 {
58     Bool fResult = FALSE;
59     ScreenPtr pScreen = pWin->drawable.pScreen;
60 
61     winWindowPriv(pWin);
62     winScreenPriv(pScreen);
63 
64 #if CYGDEBUG
65     winTrace("winCreateWindowRootless (%p)\n", pWin);
66 #endif
67 
68     WIN_UNWRAP(CreateWindow);
69     fResult = (*pScreen->CreateWindow) (pWin);
70     WIN_WRAP(CreateWindow, winCreateWindowRootless);
71 
72     pWinPriv->hRgn = NULL;
73 
74     return fResult;
75 }
76 
77 /* See Porting Layer Definition - p. 37 */
78 /* See mfb/mfbwindow.c - mfbDestroyWindow() */
79 
80 Bool
winDestroyWindowRootless(WindowPtr pWin)81 winDestroyWindowRootless(WindowPtr pWin)
82 {
83     Bool fResult = FALSE;
84     ScreenPtr pScreen = pWin->drawable.pScreen;
85 
86     winWindowPriv(pWin);
87     winScreenPriv(pScreen);
88 
89 #if CYGDEBUG
90     winTrace("winDestroyWindowRootless (%p)\n", pWin);
91 #endif
92 
93     WIN_UNWRAP(DestroyWindow);
94     fResult = (*pScreen->DestroyWindow) (pWin);
95     WIN_WRAP(DestroyWindow, winDestroyWindowRootless);
96 
97     if (pWinPriv->hRgn != NULL) {
98         DeleteObject(pWinPriv->hRgn);
99         pWinPriv->hRgn = NULL;
100     }
101 
102     winUpdateRgnRootless(pWin);
103 
104     return fResult;
105 }
106 
107 /* See Porting Layer Definition - p. 37 */
108 /* See mfb/mfbwindow.c - mfbPositionWindow() */
109 
110 Bool
winPositionWindowRootless(WindowPtr pWin,int x,int y)111 winPositionWindowRootless(WindowPtr pWin, int x, int y)
112 {
113     Bool fResult = FALSE;
114     ScreenPtr pScreen = pWin->drawable.pScreen;
115 
116     winScreenPriv(pScreen);
117 
118 #if CYGDEBUG
119     winTrace("winPositionWindowRootless (%p)\n", pWin);
120 #endif
121 
122     WIN_UNWRAP(PositionWindow);
123     fResult = (*pScreen->PositionWindow) (pWin, x, y);
124     WIN_WRAP(PositionWindow, winPositionWindowRootless);
125 
126     winUpdateRgnRootless(pWin);
127 
128     return fResult;
129 }
130 
131 /* See Porting Layer Definition - p. 37 */
132 /* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
133 
134 Bool
winChangeWindowAttributesRootless(WindowPtr pWin,unsigned long mask)135 winChangeWindowAttributesRootless(WindowPtr pWin, unsigned long mask)
136 {
137     Bool fResult = FALSE;
138     ScreenPtr pScreen = pWin->drawable.pScreen;
139 
140     winScreenPriv(pScreen);
141 
142 #if CYGDEBUG
143     winTrace("winChangeWindowAttributesRootless (%p)\n", pWin);
144 #endif
145 
146     WIN_UNWRAP(ChangeWindowAttributes);
147     fResult = (*pScreen->ChangeWindowAttributes) (pWin, mask);
148     WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesRootless);
149 
150     winUpdateRgnRootless(pWin);
151 
152     return fResult;
153 }
154 
155 /* See Porting Layer Definition - p. 37
156  * Also referred to as UnrealizeWindow
157  */
158 
159 Bool
winUnmapWindowRootless(WindowPtr pWin)160 winUnmapWindowRootless(WindowPtr pWin)
161 {
162     Bool fResult = FALSE;
163     ScreenPtr pScreen = pWin->drawable.pScreen;
164 
165     winWindowPriv(pWin);
166     winScreenPriv(pScreen);
167 
168 #if CYGDEBUG
169     winTrace("winUnmapWindowRootless (%p)\n", pWin);
170 #endif
171 
172     WIN_UNWRAP(UnrealizeWindow);
173     fResult = (*pScreen->UnrealizeWindow) (pWin);
174     WIN_WRAP(UnrealizeWindow, winUnmapWindowRootless);
175 
176     if (pWinPriv->hRgn != NULL) {
177         DeleteObject(pWinPriv->hRgn);
178         pWinPriv->hRgn = NULL;
179     }
180 
181     winUpdateRgnRootless(pWin);
182 
183     return fResult;
184 }
185 
186 /* See Porting Layer Definition - p. 37
187  * Also referred to as RealizeWindow
188  */
189 
190 Bool
winMapWindowRootless(WindowPtr pWin)191 winMapWindowRootless(WindowPtr pWin)
192 {
193     Bool fResult = FALSE;
194     ScreenPtr pScreen = pWin->drawable.pScreen;
195 
196     winScreenPriv(pScreen);
197 
198 #if CYGDEBUG
199     winTrace("winMapWindowRootless (%p)\n", pWin);
200 #endif
201 
202     WIN_UNWRAP(RealizeWindow);
203     fResult = (*pScreen->RealizeWindow) (pWin);
204     WIN_WRAP(RealizeWindow, winMapWindowRootless);
205 
206     winReshapeRootless(pWin);
207 
208     winUpdateRgnRootless(pWin);
209 
210     return fResult;
211 }
212 
213 void
winSetShapeRootless(WindowPtr pWin,int kind)214 winSetShapeRootless(WindowPtr pWin, int kind)
215 {
216     ScreenPtr pScreen = pWin->drawable.pScreen;
217 
218     winScreenPriv(pScreen);
219 
220 #if CYGDEBUG
221     winTrace("winSetShapeRootless (%p, %i)\n", pWin, kind);
222 #endif
223 
224     WIN_UNWRAP(SetShape);
225     (*pScreen->SetShape) (pWin, kind);
226     WIN_WRAP(SetShape, winSetShapeRootless);
227 
228     winReshapeRootless(pWin);
229     winUpdateRgnRootless(pWin);
230 
231     return;
232 }
233 
234 /*
235  * Local function for adding a region to the Windows window region
236  */
237 
238 static
239     int
winAddRgn(WindowPtr pWin,void * data)240 winAddRgn(WindowPtr pWin, void *data)
241 {
242     int iX, iY, iWidth, iHeight, iBorder;
243     HRGN hRgn = *(HRGN *) data;
244     HRGN hRgnWin;
245 
246     winWindowPriv(pWin);
247 
248     /* If pWin is not Root */
249     if (pWin->parent != NULL) {
250 #if CYGDEBUG
251         winDebug("winAddRgn ()\n");
252 #endif
253         if (pWin->mapped) {
254             iBorder = wBorderWidth(pWin);
255 
256             iX = pWin->drawable.x - iBorder;
257             iY = pWin->drawable.y - iBorder;
258 
259             iWidth = pWin->drawable.width + iBorder * 2;
260             iHeight = pWin->drawable.height + iBorder * 2;
261 
262             hRgnWin = CreateRectRgn(0, 0, iWidth, iHeight);
263 
264             if (hRgnWin == NULL) {
265                 ErrorF("winAddRgn - CreateRectRgn () failed\n");
266                 ErrorF("  Rect %d %d %d %d\n",
267                        iX, iY, iX + iWidth, iY + iHeight);
268             }
269 
270             if (pWinPriv->hRgn) {
271                 if (CombineRgn(hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND)
272                     == ERROR) {
273                     ErrorF("winAddRgn - CombineRgn () failed\n");
274                 }
275             }
276 
277             OffsetRgn(hRgnWin, iX, iY);
278 
279             if (CombineRgn(hRgn, hRgn, hRgnWin, RGN_OR) == ERROR) {
280                 ErrorF("winAddRgn - CombineRgn () failed\n");
281             }
282 
283             DeleteObject(hRgnWin);
284         }
285         return WT_DONTWALKCHILDREN;
286     }
287     else {
288         return WT_WALKCHILDREN;
289     }
290 }
291 
292 /*
293  * Local function to update the Windows window's region
294  */
295 
296 static
297     void
winUpdateRgnRootless(WindowPtr pWin)298 winUpdateRgnRootless(WindowPtr pWin)
299 {
300     HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
301 
302     if (hRgn != NULL) {
303         WalkTree(pWin->drawable.pScreen, winAddRgn, &hRgn);
304         SetWindowRgn(winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen,
305                      hRgn, TRUE);
306     }
307     else {
308         ErrorF("winUpdateRgnRootless - CreateRectRgn failed.\n");
309     }
310 }
311 
312 static
313     void
winReshapeRootless(WindowPtr pWin)314 winReshapeRootless(WindowPtr pWin)
315 {
316     int nRects;
317     RegionRec rrNewShape;
318     BoxPtr pShape, pRects, pEnd;
319     HRGN hRgn, hRgnRect;
320 
321     winWindowPriv(pWin);
322 
323 #if CYGDEBUG
324     winDebug("winReshapeRootless ()\n");
325 #endif
326 
327     /* Bail if the window is the root window */
328     if (pWin->parent == NULL)
329         return;
330 
331     /* Bail if the window is not top level */
332     if (pWin->parent->parent != NULL)
333         return;
334 
335     /* Free any existing window region stored in the window privates */
336     if (pWinPriv->hRgn != NULL) {
337         DeleteObject(pWinPriv->hRgn);
338         pWinPriv->hRgn = NULL;
339     }
340 
341     /* Bail if the window has no bounding region defined */
342     if (!wBoundingShape(pWin))
343         return;
344 
345     RegionNull(&rrNewShape);
346     RegionCopy(&rrNewShape, wBoundingShape(pWin));
347     RegionTranslate(&rrNewShape, pWin->borderWidth, pWin->borderWidth);
348 
349     nRects = RegionNumRects(&rrNewShape);
350     pShape = RegionRects(&rrNewShape);
351 
352     if (nRects > 0) {
353         /* Create initial empty Windows region */
354         hRgn = CreateRectRgn(0, 0, 0, 0);
355 
356         /* Loop through all rectangles in the X region */
357         for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) {
358             /* Create a Windows region for the X rectangle */
359             hRgnRect = CreateRectRgn(pRects->x1, pRects->y1,
360                                      pRects->x2, pRects->y2);
361             if (hRgnRect == NULL) {
362                 ErrorF("winReshapeRootless - CreateRectRgn() failed\n");
363             }
364 
365             /* Merge the Windows region with the accumulated region */
366             if (CombineRgn(hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) {
367                 ErrorF("winReshapeRootless - CombineRgn() failed\n");
368             }
369 
370             /* Delete the temporary Windows region */
371             DeleteObject(hRgnRect);
372         }
373 
374         /* Save a handle to the composite region in the window privates */
375         pWinPriv->hRgn = hRgn;
376     }
377 
378     RegionUninit(&rrNewShape);
379 
380     return;
381 }
382