1706f2543Smrg/*
2706f2543Smrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3706f2543Smrg *
4706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining
5706f2543Smrg * a copy of this software and associated documentation files (the
6706f2543Smrg *"Software"), to deal in the Software without restriction, including
7706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish,
8706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to
9706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to
10706f2543Smrg *the following conditions:
11706f2543Smrg *
12706f2543Smrg *The above copyright notice and this permission notice shall be
13706f2543Smrg *included in all copies or substantial portions of the Software.
14706f2543Smrg *
15706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22706f2543Smrg *
23706f2543Smrg *Except as contained in this notice, the name of the XFree86 Project
24706f2543Smrg *shall not be used in advertising or otherwise to promote the sale, use
25706f2543Smrg *or other dealings in this Software without prior written authorization
26706f2543Smrg *from the XFree86 Project.
27706f2543Smrg *
28706f2543Smrg * Authors:	Kensuke Matsuzaki
29706f2543Smrg *		Harold L Hunt II
30706f2543Smrg */
31706f2543Smrg
32706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
33706f2543Smrg#include <xwin-config.h>
34706f2543Smrg#endif
35706f2543Smrg
36706f2543Smrg#include "win.h"
37706f2543Smrg
38706f2543Smrg
39706f2543Smrg/*
40706f2543Smrg * winSetShapeMultiWindow - See Porting Layer Definition - p. 42
41706f2543Smrg */
42706f2543Smrg
43706f2543Smrgvoid
44706f2543SmrgwinSetShapeMultiWindow (WindowPtr pWin, int kind)
45706f2543Smrg{
46706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
47706f2543Smrg  winScreenPriv(pScreen);
48706f2543Smrg
49706f2543Smrg#if CYGMULTIWINDOW_DEBUG
50706f2543Smrg  ErrorF ("winSetShapeMultiWindow - pWin: %08x kind: %i\n", pWin, kind);
51706f2543Smrg#endif
52706f2543Smrg
53706f2543Smrg  WIN_UNWRAP(SetShape);
54706f2543Smrg  (*pScreen->SetShape)(pWin, kind);
55706f2543Smrg  WIN_WRAP(SetShape, winSetShapeMultiWindow);
56706f2543Smrg
57706f2543Smrg  /* Update the Windows window's shape */
58706f2543Smrg  winReshapeMultiWindow (pWin);
59706f2543Smrg  winUpdateRgnMultiWindow (pWin);
60706f2543Smrg
61706f2543Smrg  return;
62706f2543Smrg}
63706f2543Smrg
64706f2543Smrg
65706f2543Smrg/*
66706f2543Smrg * winUpdateRgnMultiWindow - Local function to update a Windows window region
67706f2543Smrg */
68706f2543Smrg
69706f2543Smrgvoid
70706f2543SmrgwinUpdateRgnMultiWindow (WindowPtr pWin)
71706f2543Smrg{
72706f2543Smrg  SetWindowRgn (winGetWindowPriv(pWin)->hWnd,
73706f2543Smrg		winGetWindowPriv(pWin)->hRgn, TRUE);
74706f2543Smrg
75706f2543Smrg  /* The system now owns the region specified by the region handle and will delete it when it is no longer needed. */
76706f2543Smrg  winGetWindowPriv(pWin)->hRgn = NULL;
77706f2543Smrg}
78706f2543Smrg
79706f2543Smrg
80706f2543Smrg/*
81706f2543Smrg * winReshapeMultiWindow - Computes the composite clipping region for a window
82706f2543Smrg */
83706f2543Smrg
84706f2543Smrgvoid
85706f2543SmrgwinReshapeMultiWindow (WindowPtr pWin)
86706f2543Smrg{
87706f2543Smrg  int		nRects;
88706f2543Smrg  RegionRec	rrNewShape;
89706f2543Smrg  BoxPtr	pShape, pRects, pEnd;
90706f2543Smrg  HRGN		hRgn, hRgnRect;
91706f2543Smrg  winWindowPriv(pWin);
92706f2543Smrg
93706f2543Smrg#if CYGDEBUG
94706f2543Smrg  winDebug ("winReshape ()\n");
95706f2543Smrg#endif
96706f2543Smrg
97706f2543Smrg  /* Bail if the window is the root window */
98706f2543Smrg  if (pWin->parent == NULL)
99706f2543Smrg    return;
100706f2543Smrg
101706f2543Smrg  /* Bail if the window is not top level */
102706f2543Smrg  if (pWin->parent->parent != NULL)
103706f2543Smrg    return;
104706f2543Smrg
105706f2543Smrg  /* Bail if Windows window handle is invalid */
106706f2543Smrg  if (pWinPriv->hWnd == NULL)
107706f2543Smrg    return;
108706f2543Smrg
109706f2543Smrg  /* Free any existing window region stored in the window privates */
110706f2543Smrg  if (pWinPriv->hRgn != NULL)
111706f2543Smrg    {
112706f2543Smrg      DeleteObject (pWinPriv->hRgn);
113706f2543Smrg      pWinPriv->hRgn = NULL;
114706f2543Smrg    }
115706f2543Smrg
116706f2543Smrg  /* Bail if the window has no bounding region defined */
117706f2543Smrg  if (!wBoundingShape (pWin))
118706f2543Smrg    return;
119706f2543Smrg
120706f2543Smrg  RegionNull(&rrNewShape);
121706f2543Smrg  RegionCopy(&rrNewShape, wBoundingShape(pWin));
122706f2543Smrg  RegionTranslate(&rrNewShape, pWin->borderWidth, pWin->borderWidth);
123706f2543Smrg
124706f2543Smrg  nRects = RegionNumRects(&rrNewShape);
125706f2543Smrg  pShape = RegionRects(&rrNewShape);
126706f2543Smrg
127706f2543Smrg  /* Don't do anything if there are no rectangles in the region */
128706f2543Smrg  if (nRects > 0)
129706f2543Smrg    {
130706f2543Smrg      RECT			rcClient;
131706f2543Smrg      RECT			rcWindow;
132706f2543Smrg      int			iOffsetX, iOffsetY;
133706f2543Smrg
134706f2543Smrg      /* Get client rectangle */
135706f2543Smrg      if (!GetClientRect (pWinPriv->hWnd, &rcClient))
136706f2543Smrg	{
137706f2543Smrg	  ErrorF ("winReshape - GetClientRect failed, bailing: %d\n",
138706f2543Smrg		  (int) GetLastError ());
139706f2543Smrg	  return;
140706f2543Smrg	}
141706f2543Smrg
142706f2543Smrg      /* Translate client rectangle coords to screen coords */
143706f2543Smrg      /* NOTE: Only transforms top and left members */
144706f2543Smrg      ClientToScreen (pWinPriv->hWnd, (LPPOINT) &rcClient);
145706f2543Smrg
146706f2543Smrg      /* Get window rectangle */
147706f2543Smrg      if (!GetWindowRect (pWinPriv->hWnd, &rcWindow))
148706f2543Smrg	{
149706f2543Smrg	  ErrorF ("winReshape - GetWindowRect failed, bailing: %d\n",
150706f2543Smrg		  (int) GetLastError ());
151706f2543Smrg	  return;
152706f2543Smrg	}
153706f2543Smrg
154706f2543Smrg      /* Calculate offset from window upper-left to client upper-left */
155706f2543Smrg      iOffsetX = rcClient.left - rcWindow.left;
156706f2543Smrg      iOffsetY = rcClient.top - rcWindow.top;
157706f2543Smrg
158706f2543Smrg      /* Create initial Windows region for title bar */
159706f2543Smrg      /* FIXME: Mean, nasty, ugly hack!!! */
160706f2543Smrg      hRgn = CreateRectRgn (0, 0, rcWindow.right, iOffsetY);
161706f2543Smrg      if (hRgn == NULL)
162706f2543Smrg	{
163706f2543Smrg	  ErrorF ("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) "
164706f2543Smrg		  "failed: %d\n",
165706f2543Smrg		  0, 0, (int) rcWindow.right, iOffsetY, (int) GetLastError ());
166706f2543Smrg	}
167706f2543Smrg
168706f2543Smrg      /* Loop through all rectangles in the X region */
169706f2543Smrg      for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++)
170706f2543Smrg        {
171706f2543Smrg	  /* Create a Windows region for the X rectangle */
172706f2543Smrg	  hRgnRect = CreateRectRgn (pRects->x1 + iOffsetX,
173706f2543Smrg				    pRects->y1 + iOffsetY,
174706f2543Smrg				    pRects->x2 + iOffsetX,
175706f2543Smrg				    pRects->y2 + iOffsetY);
176706f2543Smrg	  if (hRgnRect == NULL)
177706f2543Smrg	    {
178706f2543Smrg	      ErrorF ("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) "
179706f2543Smrg		      "failed: %d\n"
180706f2543Smrg		      "\tx1: %d x2: %d xOff: %d y1: %d y2: %d yOff: %d\n",
181706f2543Smrg		      pRects->x1 + iOffsetX,
182706f2543Smrg		      pRects->y1 + iOffsetY,
183706f2543Smrg		      pRects->x2 + iOffsetX,
184706f2543Smrg		      pRects->y2 + iOffsetY,
185706f2543Smrg		      (int) GetLastError (),
186706f2543Smrg		      pRects->x1, pRects->x2, iOffsetX,
187706f2543Smrg		      pRects->y1, pRects->y2, iOffsetY);
188706f2543Smrg	    }
189706f2543Smrg
190706f2543Smrg	  /* Merge the Windows region with the accumulated region */
191706f2543Smrg	  if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR)
192706f2543Smrg	    {
193706f2543Smrg	      ErrorF ("winReshape - CombineRgn () failed: %d\n",
194706f2543Smrg		      (int) GetLastError ());
195706f2543Smrg	    }
196706f2543Smrg
197706f2543Smrg	  /* Delete the temporary Windows region */
198706f2543Smrg	  DeleteObject (hRgnRect);
199706f2543Smrg        }
200706f2543Smrg
201706f2543Smrg      /* Save a handle to the composite region in the window privates */
202706f2543Smrg      pWinPriv->hRgn = hRgn;
203706f2543Smrg    }
204706f2543Smrg
205706f2543Smrg  RegionUninit(&rrNewShape);
206706f2543Smrg
207706f2543Smrg  return;
208706f2543Smrg}
209