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:	Kensuke Matsuzaki
29 *		Harold L Hunt II
30 */
31
32#ifdef HAVE_XWIN_CONFIG_H
33#include <xwin-config.h>
34#endif
35
36#include "win.h"
37
38
39/*
40 * winSetShapeMultiWindow - See Porting Layer Definition - p. 42
41 */
42
43void
44winSetShapeMultiWindow (WindowPtr pWin, int kind)
45{
46  ScreenPtr		pScreen = pWin->drawable.pScreen;
47  winScreenPriv(pScreen);
48
49#if CYGMULTIWINDOW_DEBUG
50  ErrorF ("winSetShapeMultiWindow - pWin: %08x kind: %i\n", pWin, kind);
51#endif
52
53  WIN_UNWRAP(SetShape);
54  (*pScreen->SetShape)(pWin, kind);
55  WIN_WRAP(SetShape, winSetShapeMultiWindow);
56
57  /* Update the Windows window's shape */
58  winReshapeMultiWindow (pWin);
59  winUpdateRgnMultiWindow (pWin);
60
61  return;
62}
63
64
65/*
66 * winUpdateRgnMultiWindow - Local function to update a Windows window region
67 */
68
69void
70winUpdateRgnMultiWindow (WindowPtr pWin)
71{
72  SetWindowRgn (winGetWindowPriv(pWin)->hWnd,
73		winGetWindowPriv(pWin)->hRgn, TRUE);
74
75  /* The system now owns the region specified by the region handle and will delete it when it is no longer needed. */
76  winGetWindowPriv(pWin)->hRgn = NULL;
77}
78
79
80/*
81 * winReshapeMultiWindow - Computes the composite clipping region for a window
82 */
83
84void
85winReshapeMultiWindow (WindowPtr pWin)
86{
87  int		nRects;
88  RegionRec	rrNewShape;
89  BoxPtr	pShape, pRects, pEnd;
90  HRGN		hRgn, hRgnRect;
91  winWindowPriv(pWin);
92
93#if CYGDEBUG
94  winDebug ("winReshape ()\n");
95#endif
96
97  /* Bail if the window is the root window */
98  if (pWin->parent == NULL)
99    return;
100
101  /* Bail if the window is not top level */
102  if (pWin->parent->parent != NULL)
103    return;
104
105  /* Bail if Windows window handle is invalid */
106  if (pWinPriv->hWnd == NULL)
107    return;
108
109  /* Free any existing window region stored in the window privates */
110  if (pWinPriv->hRgn != NULL)
111    {
112      DeleteObject (pWinPriv->hRgn);
113      pWinPriv->hRgn = NULL;
114    }
115
116  /* Bail if the window has no bounding region defined */
117  if (!wBoundingShape (pWin))
118    return;
119
120  RegionNull(&rrNewShape);
121  RegionCopy(&rrNewShape, wBoundingShape(pWin));
122  RegionTranslate(&rrNewShape, pWin->borderWidth, pWin->borderWidth);
123
124  nRects = RegionNumRects(&rrNewShape);
125  pShape = RegionRects(&rrNewShape);
126
127  /* Don't do anything if there are no rectangles in the region */
128  if (nRects > 0)
129    {
130      RECT			rcClient;
131      RECT			rcWindow;
132      int			iOffsetX, iOffsetY;
133
134      /* Get client rectangle */
135      if (!GetClientRect (pWinPriv->hWnd, &rcClient))
136	{
137	  ErrorF ("winReshape - GetClientRect failed, bailing: %d\n",
138		  (int) GetLastError ());
139	  return;
140	}
141
142      /* Translate client rectangle coords to screen coords */
143      /* NOTE: Only transforms top and left members */
144      ClientToScreen (pWinPriv->hWnd, (LPPOINT) &rcClient);
145
146      /* Get window rectangle */
147      if (!GetWindowRect (pWinPriv->hWnd, &rcWindow))
148	{
149	  ErrorF ("winReshape - GetWindowRect failed, bailing: %d\n",
150		  (int) GetLastError ());
151	  return;
152	}
153
154      /* Calculate offset from window upper-left to client upper-left */
155      iOffsetX = rcClient.left - rcWindow.left;
156      iOffsetY = rcClient.top - rcWindow.top;
157
158      /* Create initial Windows region for title bar */
159      /* FIXME: Mean, nasty, ugly hack!!! */
160      hRgn = CreateRectRgn (0, 0, rcWindow.right, iOffsetY);
161      if (hRgn == NULL)
162	{
163	  ErrorF ("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) "
164		  "failed: %d\n",
165		  0, 0, (int) rcWindow.right, iOffsetY, (int) GetLastError ());
166	}
167
168      /* Loop through all rectangles in the X region */
169      for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++)
170        {
171	  /* Create a Windows region for the X rectangle */
172	  hRgnRect = CreateRectRgn (pRects->x1 + iOffsetX,
173				    pRects->y1 + iOffsetY,
174				    pRects->x2 + iOffsetX,
175				    pRects->y2 + iOffsetY);
176	  if (hRgnRect == NULL)
177	    {
178	      ErrorF ("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) "
179		      "failed: %d\n"
180		      "\tx1: %d x2: %d xOff: %d y1: %d y2: %d yOff: %d\n",
181		      pRects->x1 + iOffsetX,
182		      pRects->y1 + iOffsetY,
183		      pRects->x2 + iOffsetX,
184		      pRects->y2 + iOffsetY,
185		      (int) GetLastError (),
186		      pRects->x1, pRects->x2, iOffsetX,
187		      pRects->y1, pRects->y2, iOffsetY);
188	    }
189
190	  /* Merge the Windows region with the accumulated region */
191	  if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR)
192	    {
193	      ErrorF ("winReshape - CombineRgn () failed: %d\n",
194		      (int) GetLastError ());
195	    }
196
197	  /* Delete the temporary Windows region */
198	  DeleteObject (hRgnRect);
199        }
200
201      /* Save a handle to the composite region in the window privates */
202      pWinPriv->hRgn = hRgn;
203    }
204
205  RegionUninit(&rrNewShape);
206
207  return;
208}
209