winwindow.c revision 35c4bbdf
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
41static int
42 winAddRgn(WindowPtr pWindow, void *data);
43
44static
45    void
46 winUpdateRgnRootless(WindowPtr pWindow);
47
48static
49    void
50 winReshapeRootless(WindowPtr pWin);
51
52/* See Porting Layer Definition - p. 37 */
53/* See mfb/mfbwindow.c - mfbCreateWindow() */
54
55Bool
56winCreateWindowRootless(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
80Bool
81winDestroyWindowRootless(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
110Bool
111winPositionWindowRootless(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
134Bool
135winChangeWindowAttributesRootless(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
159Bool
160winUnmapWindowRootless(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
190Bool
191winMapWindowRootless(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
213void
214winSetShapeRootless(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
238static
239    int
240winAddRgn(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
296static
297    void
298winUpdateRgnRootless(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
312static
313    void
314winReshapeRootless(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