105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
305b261ecSmrg *
405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining
505b261ecSmrg * a copy of this software and associated documentation files (the
605b261ecSmrg *"Software"), to deal in the Software without restriction, including
705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish,
805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to
905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to
1005b261ecSmrg *the following conditions:
1105b261ecSmrg *
1205b261ecSmrg *The above copyright notice and this permission notice shall be
1305b261ecSmrg *included in all copies or substantial portions of the Software.
1405b261ecSmrg *
1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project
2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use
2505b261ecSmrg *or other dealings in this Software without prior written authorization
2605b261ecSmrg *from the XFree86 Project.
2705b261ecSmrg *
2805b261ecSmrg * Authors:	Harold L Hunt II
2905b261ecSmrg *		Kensuke Matsuzaki
3005b261ecSmrg */
3105b261ecSmrg
3205b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3305b261ecSmrg#include <xwin-config.h>
3405b261ecSmrg#endif
3505b261ecSmrg#include "win.h"
3605b261ecSmrg
3705b261ecSmrg/*
3805b261ecSmrg * Prototypes for local functions
3905b261ecSmrg */
4005b261ecSmrg
4105b261ecSmrgstatic int
4235c4bbdfSmrg winAddRgn(WindowPtr pWindow, void *data);
4305b261ecSmrg
4405b261ecSmrgstatic
4535c4bbdfSmrg    void
4635c4bbdfSmrg winUpdateRgnRootless(WindowPtr pWindow);
4705b261ecSmrg
4805b261ecSmrgstatic
4935c4bbdfSmrg    void
5035c4bbdfSmrg winReshapeRootless(WindowPtr pWin);
5105b261ecSmrg
5205b261ecSmrg/* See Porting Layer Definition - p. 37 */
5305b261ecSmrg/* See mfb/mfbwindow.c - mfbCreateWindow() */
5405b261ecSmrg
5505b261ecSmrgBool
5635c4bbdfSmrgwinCreateWindowRootless(WindowPtr pWin)
5705b261ecSmrg{
5835c4bbdfSmrg    Bool fResult = FALSE;
5935c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
6035c4bbdfSmrg
6135c4bbdfSmrg    winWindowPriv(pWin);
6235c4bbdfSmrg    winScreenPriv(pScreen);
6305b261ecSmrg
6405b261ecSmrg#if CYGDEBUG
6535c4bbdfSmrg    winTrace("winCreateWindowRootless (%p)\n", pWin);
6605b261ecSmrg#endif
6705b261ecSmrg
6835c4bbdfSmrg    WIN_UNWRAP(CreateWindow);
6935c4bbdfSmrg    fResult = (*pScreen->CreateWindow) (pWin);
7035c4bbdfSmrg    WIN_WRAP(CreateWindow, winCreateWindowRootless);
7105b261ecSmrg
7235c4bbdfSmrg    pWinPriv->hRgn = NULL;
7305b261ecSmrg
7435c4bbdfSmrg    return fResult;
7535c4bbdfSmrg}
7605b261ecSmrg
7705b261ecSmrg/* See Porting Layer Definition - p. 37 */
7805b261ecSmrg/* See mfb/mfbwindow.c - mfbDestroyWindow() */
7905b261ecSmrg
8005b261ecSmrgBool
8135c4bbdfSmrgwinDestroyWindowRootless(WindowPtr pWin)
8205b261ecSmrg{
8335c4bbdfSmrg    Bool fResult = FALSE;
8435c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
8535c4bbdfSmrg
8635c4bbdfSmrg    winWindowPriv(pWin);
8735c4bbdfSmrg    winScreenPriv(pScreen);
8805b261ecSmrg
8905b261ecSmrg#if CYGDEBUG
9035c4bbdfSmrg    winTrace("winDestroyWindowRootless (%p)\n", pWin);
9105b261ecSmrg#endif
9205b261ecSmrg
9335c4bbdfSmrg    WIN_UNWRAP(DestroyWindow);
9435c4bbdfSmrg    fResult = (*pScreen->DestroyWindow) (pWin);
9535c4bbdfSmrg    WIN_WRAP(DestroyWindow, winDestroyWindowRootless);
9605b261ecSmrg
9735c4bbdfSmrg    if (pWinPriv->hRgn != NULL) {
9835c4bbdfSmrg        DeleteObject(pWinPriv->hRgn);
9935c4bbdfSmrg        pWinPriv->hRgn = NULL;
10035c4bbdfSmrg    }
10135c4bbdfSmrg
10235c4bbdfSmrg    winUpdateRgnRootless(pWin);
10305b261ecSmrg
10435c4bbdfSmrg    return fResult;
10535c4bbdfSmrg}
10605b261ecSmrg
10705b261ecSmrg/* See Porting Layer Definition - p. 37 */
10805b261ecSmrg/* See mfb/mfbwindow.c - mfbPositionWindow() */
10905b261ecSmrg
11005b261ecSmrgBool
11135c4bbdfSmrgwinPositionWindowRootless(WindowPtr pWin, int x, int y)
11205b261ecSmrg{
11335c4bbdfSmrg    Bool fResult = FALSE;
11435c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
11505b261ecSmrg
11635c4bbdfSmrg    winScreenPriv(pScreen);
11705b261ecSmrg
11835c4bbdfSmrg#if CYGDEBUG
11935c4bbdfSmrg    winTrace("winPositionWindowRootless (%p)\n", pWin);
12005b261ecSmrg#endif
12105b261ecSmrg
12235c4bbdfSmrg    WIN_UNWRAP(PositionWindow);
12335c4bbdfSmrg    fResult = (*pScreen->PositionWindow) (pWin, x, y);
12435c4bbdfSmrg    WIN_WRAP(PositionWindow, winPositionWindowRootless);
12505b261ecSmrg
12635c4bbdfSmrg    winUpdateRgnRootless(pWin);
12705b261ecSmrg
12835c4bbdfSmrg    return fResult;
12905b261ecSmrg}
13005b261ecSmrg
13105b261ecSmrg/* See Porting Layer Definition - p. 37 */
13205b261ecSmrg/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
13305b261ecSmrg
13405b261ecSmrgBool
13535c4bbdfSmrgwinChangeWindowAttributesRootless(WindowPtr pWin, unsigned long mask)
13605b261ecSmrg{
13735c4bbdfSmrg    Bool fResult = FALSE;
13835c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
13935c4bbdfSmrg
14035c4bbdfSmrg    winScreenPriv(pScreen);
14105b261ecSmrg
14205b261ecSmrg#if CYGDEBUG
14335c4bbdfSmrg    winTrace("winChangeWindowAttributesRootless (%p)\n", pWin);
14405b261ecSmrg#endif
14505b261ecSmrg
14635c4bbdfSmrg    WIN_UNWRAP(ChangeWindowAttributes);
14735c4bbdfSmrg    fResult = (*pScreen->ChangeWindowAttributes) (pWin, mask);
14835c4bbdfSmrg    WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesRootless);
14935c4bbdfSmrg
15035c4bbdfSmrg    winUpdateRgnRootless(pWin);
15135c4bbdfSmrg
15235c4bbdfSmrg    return fResult;
15335c4bbdfSmrg}
15405b261ecSmrg
15505b261ecSmrg/* See Porting Layer Definition - p. 37
15605b261ecSmrg * Also referred to as UnrealizeWindow
15705b261ecSmrg */
15805b261ecSmrg
15905b261ecSmrgBool
16035c4bbdfSmrgwinUnmapWindowRootless(WindowPtr pWin)
16105b261ecSmrg{
16235c4bbdfSmrg    Bool fResult = FALSE;
16335c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
16435c4bbdfSmrg
16535c4bbdfSmrg    winWindowPriv(pWin);
16635c4bbdfSmrg    winScreenPriv(pScreen);
16705b261ecSmrg
16805b261ecSmrg#if CYGDEBUG
16935c4bbdfSmrg    winTrace("winUnmapWindowRootless (%p)\n", pWin);
17005b261ecSmrg#endif
17105b261ecSmrg
17235c4bbdfSmrg    WIN_UNWRAP(UnrealizeWindow);
17335c4bbdfSmrg    fResult = (*pScreen->UnrealizeWindow) (pWin);
17435c4bbdfSmrg    WIN_WRAP(UnrealizeWindow, winUnmapWindowRootless);
17535c4bbdfSmrg
17635c4bbdfSmrg    if (pWinPriv->hRgn != NULL) {
17735c4bbdfSmrg        DeleteObject(pWinPriv->hRgn);
17835c4bbdfSmrg        pWinPriv->hRgn = NULL;
17935c4bbdfSmrg    }
18035c4bbdfSmrg
18135c4bbdfSmrg    winUpdateRgnRootless(pWin);
18205b261ecSmrg
18335c4bbdfSmrg    return fResult;
18435c4bbdfSmrg}
18505b261ecSmrg
18605b261ecSmrg/* See Porting Layer Definition - p. 37
18705b261ecSmrg * Also referred to as RealizeWindow
18805b261ecSmrg */
18905b261ecSmrg
19005b261ecSmrgBool
19135c4bbdfSmrgwinMapWindowRootless(WindowPtr pWin)
19205b261ecSmrg{
19335c4bbdfSmrg    Bool fResult = FALSE;
19435c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
19505b261ecSmrg
19635c4bbdfSmrg    winScreenPriv(pScreen);
19705b261ecSmrg
19805b261ecSmrg#if CYGDEBUG
19935c4bbdfSmrg    winTrace("winMapWindowRootless (%p)\n", pWin);
20005b261ecSmrg#endif
20105b261ecSmrg
20235c4bbdfSmrg    WIN_UNWRAP(RealizeWindow);
20335c4bbdfSmrg    fResult = (*pScreen->RealizeWindow) (pWin);
20435c4bbdfSmrg    WIN_WRAP(RealizeWindow, winMapWindowRootless);
20505b261ecSmrg
20635c4bbdfSmrg    winReshapeRootless(pWin);
20705b261ecSmrg
20835c4bbdfSmrg    winUpdateRgnRootless(pWin);
20905b261ecSmrg
21035c4bbdfSmrg    return fResult;
21105b261ecSmrg}
21205b261ecSmrg
21335c4bbdfSmrgvoid
21435c4bbdfSmrgwinSetShapeRootless(WindowPtr pWin, int kind)
21505b261ecSmrg{
21635c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
21705b261ecSmrg
21835c4bbdfSmrg    winScreenPriv(pScreen);
21905b261ecSmrg
22005b261ecSmrg#if CYGDEBUG
22135c4bbdfSmrg    winTrace("winSetShapeRootless (%p, %i)\n", pWin, kind);
22205b261ecSmrg#endif
22305b261ecSmrg
22435c4bbdfSmrg    WIN_UNWRAP(SetShape);
22535c4bbdfSmrg    (*pScreen->SetShape) (pWin, kind);
22635c4bbdfSmrg    WIN_WRAP(SetShape, winSetShapeRootless);
22705b261ecSmrg
22835c4bbdfSmrg    winReshapeRootless(pWin);
22935c4bbdfSmrg    winUpdateRgnRootless(pWin);
23005b261ecSmrg
23135c4bbdfSmrg    return;
23205b261ecSmrg}
23305b261ecSmrg
23435c4bbdfSmrg/*
23535c4bbdfSmrg * Local function for adding a region to the Windows window region
23605b261ecSmrg */
23705b261ecSmrg
23835c4bbdfSmrgstatic
23935c4bbdfSmrg    int
24035c4bbdfSmrgwinAddRgn(WindowPtr pWin, void *data)
24105b261ecSmrg{
24235c4bbdfSmrg    int iX, iY, iWidth, iHeight, iBorder;
24335c4bbdfSmrg    HRGN hRgn = *(HRGN *) data;
24435c4bbdfSmrg    HRGN hRgnWin;
24505b261ecSmrg
24635c4bbdfSmrg    winWindowPriv(pWin);
24705b261ecSmrg
24835c4bbdfSmrg    /* If pWin is not Root */
24935c4bbdfSmrg    if (pWin->parent != NULL) {
25005b261ecSmrg#if CYGDEBUG
25135c4bbdfSmrg        winDebug("winAddRgn ()\n");
25205b261ecSmrg#endif
25335c4bbdfSmrg        if (pWin->mapped) {
25435c4bbdfSmrg            iBorder = wBorderWidth(pWin);
25505b261ecSmrg
25635c4bbdfSmrg            iX = pWin->drawable.x - iBorder;
25735c4bbdfSmrg            iY = pWin->drawable.y - iBorder;
25805b261ecSmrg
25935c4bbdfSmrg            iWidth = pWin->drawable.width + iBorder * 2;
26035c4bbdfSmrg            iHeight = pWin->drawable.height + iBorder * 2;
26105b261ecSmrg
26235c4bbdfSmrg            hRgnWin = CreateRectRgn(0, 0, iWidth, iHeight);
26305b261ecSmrg
26435c4bbdfSmrg            if (hRgnWin == NULL) {
26535c4bbdfSmrg                ErrorF("winAddRgn - CreateRectRgn () failed\n");
26635c4bbdfSmrg                ErrorF("  Rect %d %d %d %d\n",
26735c4bbdfSmrg                       iX, iY, iX + iWidth, iY + iHeight);
26835c4bbdfSmrg            }
26905b261ecSmrg
27035c4bbdfSmrg            if (pWinPriv->hRgn) {
27135c4bbdfSmrg                if (CombineRgn(hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND)
27235c4bbdfSmrg                    == ERROR) {
27335c4bbdfSmrg                    ErrorF("winAddRgn - CombineRgn () failed\n");
27435c4bbdfSmrg                }
27535c4bbdfSmrg            }
27605b261ecSmrg
27735c4bbdfSmrg            OffsetRgn(hRgnWin, iX, iY);
27805b261ecSmrg
27935c4bbdfSmrg            if (CombineRgn(hRgn, hRgn, hRgnWin, RGN_OR) == ERROR) {
28035c4bbdfSmrg                ErrorF("winAddRgn - CombineRgn () failed\n");
28135c4bbdfSmrg            }
28205b261ecSmrg
28335c4bbdfSmrg            DeleteObject(hRgnWin);
28435c4bbdfSmrg        }
28535c4bbdfSmrg        return WT_DONTWALKCHILDREN;
28605b261ecSmrg    }
28735c4bbdfSmrg    else {
28835c4bbdfSmrg        return WT_WALKCHILDREN;
28905b261ecSmrg    }
29005b261ecSmrg}
29105b261ecSmrg
29205b261ecSmrg/*
29305b261ecSmrg * Local function to update the Windows window's region
29405b261ecSmrg */
29505b261ecSmrg
29605b261ecSmrgstatic
29735c4bbdfSmrg    void
29835c4bbdfSmrgwinUpdateRgnRootless(WindowPtr pWin)
29905b261ecSmrg{
30035c4bbdfSmrg    HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
30135c4bbdfSmrg
30235c4bbdfSmrg    if (hRgn != NULL) {
30335c4bbdfSmrg        WalkTree(pWin->drawable.pScreen, winAddRgn, &hRgn);
30435c4bbdfSmrg        SetWindowRgn(winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen,
30535c4bbdfSmrg                     hRgn, TRUE);
30605b261ecSmrg    }
30735c4bbdfSmrg    else {
30835c4bbdfSmrg        ErrorF("winUpdateRgnRootless - CreateRectRgn failed.\n");
30905b261ecSmrg    }
31005b261ecSmrg}
31105b261ecSmrg
31205b261ecSmrgstatic
31335c4bbdfSmrg    void
31435c4bbdfSmrgwinReshapeRootless(WindowPtr pWin)
31505b261ecSmrg{
31635c4bbdfSmrg    int nRects;
31735c4bbdfSmrg    RegionRec rrNewShape;
31835c4bbdfSmrg    BoxPtr pShape, pRects, pEnd;
31935c4bbdfSmrg    HRGN hRgn, hRgnRect;
32035c4bbdfSmrg
32135c4bbdfSmrg    winWindowPriv(pWin);
32205b261ecSmrg
32305b261ecSmrg#if CYGDEBUG
32435c4bbdfSmrg    winDebug("winReshapeRootless ()\n");
32505b261ecSmrg#endif
32605b261ecSmrg
32735c4bbdfSmrg    /* Bail if the window is the root window */
32835c4bbdfSmrg    if (pWin->parent == NULL)
32935c4bbdfSmrg        return;
33005b261ecSmrg
33135c4bbdfSmrg    /* Bail if the window is not top level */
33235c4bbdfSmrg    if (pWin->parent->parent != NULL)
33335c4bbdfSmrg        return;
33405b261ecSmrg
33535c4bbdfSmrg    /* Free any existing window region stored in the window privates */
33635c4bbdfSmrg    if (pWinPriv->hRgn != NULL) {
33735c4bbdfSmrg        DeleteObject(pWinPriv->hRgn);
33835c4bbdfSmrg        pWinPriv->hRgn = NULL;
33905b261ecSmrg    }
34005b261ecSmrg
34135c4bbdfSmrg    /* Bail if the window has no bounding region defined */
34235c4bbdfSmrg    if (!wBoundingShape(pWin))
34335c4bbdfSmrg        return;
34435c4bbdfSmrg
34535c4bbdfSmrg    RegionNull(&rrNewShape);
34635c4bbdfSmrg    RegionCopy(&rrNewShape, wBoundingShape(pWin));
34735c4bbdfSmrg    RegionTranslate(&rrNewShape, pWin->borderWidth, pWin->borderWidth);
34835c4bbdfSmrg
34935c4bbdfSmrg    nRects = RegionNumRects(&rrNewShape);
35035c4bbdfSmrg    pShape = RegionRects(&rrNewShape);
35135c4bbdfSmrg
35235c4bbdfSmrg    if (nRects > 0) {
35335c4bbdfSmrg        /* Create initial empty Windows region */
35435c4bbdfSmrg        hRgn = CreateRectRgn(0, 0, 0, 0);
35535c4bbdfSmrg
35635c4bbdfSmrg        /* Loop through all rectangles in the X region */
35735c4bbdfSmrg        for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) {
35835c4bbdfSmrg            /* Create a Windows region for the X rectangle */
35935c4bbdfSmrg            hRgnRect = CreateRectRgn(pRects->x1, pRects->y1,
36035c4bbdfSmrg                                     pRects->x2, pRects->y2);
36135c4bbdfSmrg            if (hRgnRect == NULL) {
36235c4bbdfSmrg                ErrorF("winReshapeRootless - CreateRectRgn() failed\n");
36335c4bbdfSmrg            }
36435c4bbdfSmrg
36535c4bbdfSmrg            /* Merge the Windows region with the accumulated region */
36635c4bbdfSmrg            if (CombineRgn(hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) {
36735c4bbdfSmrg                ErrorF("winReshapeRootless - CombineRgn() failed\n");
36835c4bbdfSmrg            }
36935c4bbdfSmrg
37035c4bbdfSmrg            /* Delete the temporary Windows region */
37135c4bbdfSmrg            DeleteObject(hRgnRect);
37205b261ecSmrg        }
37335c4bbdfSmrg
37435c4bbdfSmrg        /* Save a handle to the composite region in the window privates */
37535c4bbdfSmrg        pWinPriv->hRgn = hRgn;
37605b261ecSmrg    }
37705b261ecSmrg
37835c4bbdfSmrg    RegionUninit(&rrNewShape);
37935c4bbdfSmrg
38035c4bbdfSmrg    return;
38105b261ecSmrg}
382