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/*
39 * Prototypes for local functions
40 */
41
42static int
43winAddRgn (WindowPtr pWindow, pointer data);
44
45static
46void
47winUpdateRgnRootless (WindowPtr pWindow);
48
49static
50void
51winReshapeRootless (WindowPtr pWin);
52
53
54#ifdef XWIN_NATIVEGDI
55/* See Porting Layer Definition - p. 37 */
56/* See mfb/mfbwindow.c - mfbCreateWindow() */
57
58Bool
59winCreateWindowNativeGDI (WindowPtr pWin)
60{
61  Bool			fResult = TRUE;
62  ScreenPtr		pScreen = pWin->drawable.pScreen;
63  winWindowPriv(pWin);
64  winScreenPriv(pScreen);
65
66#if CYGDEBUG
67  winTrace ("winCreateWindowNativeGDI (%p)\n", pWin);
68#endif
69
70  WIN_UNWRAP(CreateWindow);
71  fResult = (*pScreen->CreateWindow) (pWin);
72  WIN_WRAP(CreateWindow, winCreateWindowNativeGDI);
73
74  return fResult;
75}
76
77
78/* See Porting Layer Definition - p. 37 */
79/* See mfb/mfbwindow.c - mfbDestroyWindow() */
80
81Bool
82winDestroyWindowNativeGDI (WindowPtr pWin)
83{
84  Bool			fResult = TRUE;
85  ScreenPtr		pScreen = pWin->drawable.pScreen;
86  winWindowPriv(pWin);
87  winScreenPriv(pScreen);
88
89#if CYGDEBUG
90  winTrace ("winDestroyWindowNativeGDI (%p)\n", pWin);
91#endif
92
93  WIN_UNWRAP(DestroyWindow);
94  fResult = (*pScreen->DestroyWindow)(pWin);
95  WIN_WRAP(DestroyWindow, winDestroyWindowNativeGDI);
96
97  return fResult;
98}
99
100
101/* See Porting Layer Definition - p. 37 */
102/* See mfb/mfbwindow.c - mfbPositionWindow() */
103
104Bool
105winPositionWindowNativeGDI (WindowPtr pWin, int x, int y)
106{
107  Bool			fResult = TRUE;
108  ScreenPtr		pScreen = pWin->drawable.pScreen;
109  winWindowPriv(pWin);
110  winScreenPriv(pScreen);
111
112#if CYGDEBUG
113  winTrace ("winPositionWindowNativeGDI (%p)\n", pWin);
114#endif
115
116  WIN_UNWRAP(PositionWindow);
117  fResult = (*pScreen->PositionWindow)(pWin, x, y);
118  WIN_WRAP(PositionWindow, winPositionWindowNativeGDI);
119
120  return fResult;
121}
122
123
124/* See Porting Layer Definition - p. 39 */
125/* See mfb/mfbwindow.c - mfbCopyWindow() */
126
127void
128winCopyWindowNativeGDI (WindowPtr pWin,
129			DDXPointRec ptOldOrg,
130			RegionPtr prgnSrc)
131{
132  DDXPointPtr		pptSrc;
133  DDXPointPtr		ppt;
134  RegionPtr		prgnDst;
135  BoxPtr		pBox;
136  int			dx, dy;
137  int			i, nbox;
138  WindowPtr		pwinRoot;
139  BoxPtr		pBoxDst;
140  ScreenPtr		pScreen = pWin->drawable.pScreen;
141  winScreenPriv(pScreen);
142
143#if 0
144  ErrorF ("winCopyWindow\n");
145#endif
146
147  /* Get a pointer to the root window */
148  pwinRoot = pWin->drawable.pScreen->root;
149
150  /* Create a region for the destination */
151  prgnDst = RegionCreate(NULL, 1);
152
153  /* Calculate the shift from the source to the destination */
154  dx = ptOldOrg.x - pWin->drawable.x;
155  dy = ptOldOrg.y - pWin->drawable.y;
156
157  /* Translate the region from the destination to the source? */
158  RegionTranslate(prgnSrc, -dx, -dy);
159  RegionIntersect(prgnDst, &pWin->borderClip,
160		   prgnSrc);
161
162  /* Get a pointer to the first box in the region to be copied */
163  pBox = RegionRects(prgnDst);
164
165  /* Get the number of boxes in the region */
166  nbox = RegionNumRects(prgnDst);
167
168  /* Allocate source points for each box */
169  if(!(pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec))))
170    return;
171
172  /* Set an iterator pointer */
173  ppt = pptSrc;
174
175  /* Calculate the source point of each box? */
176  for (i = nbox; --i >= 0; ppt++, pBox++)
177    {
178      ppt->x = pBox->x1 + dx;
179      ppt->y = pBox->y1 + dy;
180    }
181
182  /* Setup loop pointers again */
183  pBoxDst = RegionRects(prgnDst);
184  ppt = pptSrc;
185
186#if 0
187  ErrorF ("winCopyWindow - x1\tx2\ty1\ty2\tx\ty\n");
188#endif
189
190  /* BitBlt each source to the destination point */
191  for (i = nbox; --i >= 0; pBoxDst++, ppt++)
192    {
193#if 0
194      ErrorF ("winCopyWindow - %d\t%d\t%d\t%d\t%d\t%d\n",
195	      pBoxDst->x1, pBoxDst->x2, pBoxDst->y1, pBoxDst->y2,
196	      ppt->x, ppt->y);
197#endif
198
199      BitBlt (pScreenPriv->hdcScreen,
200	      pBoxDst->x1, pBoxDst->y1,
201	      pBoxDst->x2 - pBoxDst->x1, pBoxDst->y2 - pBoxDst->y1,
202	      pScreenPriv->hdcScreen,
203	      ppt->x, ppt->y,
204	      SRCCOPY);
205    }
206
207  /* Cleanup the regions, etc. */
208  free(pptSrc);
209  RegionDestroy(prgnDst);
210}
211
212
213/* See Porting Layer Definition - p. 37 */
214/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
215
216Bool
217winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask)
218{
219  Bool			fResult = TRUE;
220  ScreenPtr		pScreen = pWin->drawable.pScreen;
221  winWindowPriv(pWin);
222  winScreenPriv(pScreen);
223
224#if CYGDEBUG
225  winTrace ("winChangeWindowAttributesNativeGDI (%p)\n", pWin);
226#endif
227
228  WIN_UNWRAP(ChangeWindowAttributes);
229  fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
230  WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesNativeGDI);
231
232  /*
233   * NOTE: We do not currently need to do anything here.
234   */
235
236  return fResult;
237}
238
239
240/* See Porting Layer Definition - p. 37
241 * Also referred to as UnrealizeWindow
242 */
243
244Bool
245winUnmapWindowNativeGDI (WindowPtr pWin)
246{
247  Bool			fResult = TRUE;
248  ScreenPtr		pScreen = pWin->drawable.pScreen;
249  winWindowPriv(pWin);
250  winScreenPriv(pScreen);
251
252#if CYGDEBUG
253  winTrace ("winUnmapWindowNativeGDI (%p)\n", pWin);
254#endif
255
256  WIN_UNWRAP(UnrealizeWindow);
257  fResult = (*pScreen->UnrealizeWindow)(pWin);
258  WIN_WRAP(UnrealizeWindow, winUnmapWindowNativeGDI);
259
260  return fResult;
261}
262
263
264/* See Porting Layer Definition - p. 37
265 * Also referred to as RealizeWindow
266 */
267
268Bool
269winMapWindowNativeGDI (WindowPtr pWin)
270{
271  Bool			fResult = TRUE;
272  ScreenPtr		pScreen = pWin->drawable.pScreen;
273  winWindowPriv(pWin);
274  winScreenPriv(pScreen);
275
276#if CYGDEBUG
277  winTrace ("winMapWindowNativeGDI (%p)\n", pWin);
278#endif
279
280  WIN_UNWRAP(RealizeWindow);
281  fResult = (*pScreen->RealizeWindow)(pWin);
282  WIN_WRAP(RealizeWindow, winMapWindowMultiWindow);
283
284  return fResult;
285
286}
287#endif
288
289
290/* See Porting Layer Definition - p. 37 */
291/* See mfb/mfbwindow.c - mfbCreateWindow() */
292
293Bool
294winCreateWindowRootless (WindowPtr pWin)
295{
296  Bool			fResult = FALSE;
297  ScreenPtr		pScreen = pWin->drawable.pScreen;
298  winWindowPriv(pWin);
299  winScreenPriv(pScreen);
300
301#if CYGDEBUG
302  winTrace ("winCreateWindowRootless (%p)\n", pWin);
303#endif
304
305  WIN_UNWRAP(CreateWindow);
306  fResult = (*pScreen->CreateWindow) (pWin);
307  WIN_WRAP(CreateWindow, winCreateWindowRootless);
308
309  pWinPriv->hRgn = NULL;
310
311  return fResult;
312}
313
314
315/* See Porting Layer Definition - p. 37 */
316/* See mfb/mfbwindow.c - mfbDestroyWindow() */
317
318Bool
319winDestroyWindowRootless (WindowPtr pWin)
320{
321  Bool			fResult = FALSE;
322  ScreenPtr		pScreen = pWin->drawable.pScreen;
323  winWindowPriv(pWin);
324  winScreenPriv(pScreen);
325
326#if CYGDEBUG
327  winTrace ("winDestroyWindowRootless (%p)\n", pWin);
328#endif
329
330  WIN_UNWRAP(DestroyWindow);
331  fResult = (*pScreen->DestroyWindow)(pWin);
332  WIN_WRAP(DestroyWindow, winDestroyWindowRootless);
333
334  if (pWinPriv->hRgn != NULL)
335    {
336      DeleteObject(pWinPriv->hRgn);
337      pWinPriv->hRgn = NULL;
338    }
339
340  winUpdateRgnRootless (pWin);
341
342  return fResult;
343}
344
345
346/* See Porting Layer Definition - p. 37 */
347/* See mfb/mfbwindow.c - mfbPositionWindow() */
348
349Bool
350winPositionWindowRootless (WindowPtr pWin, int x, int y)
351{
352  Bool			fResult = FALSE;
353  ScreenPtr		pScreen = pWin->drawable.pScreen;
354  winScreenPriv(pScreen);
355
356
357#if CYGDEBUG
358  winTrace ("winPositionWindowRootless (%p)\n", pWin);
359#endif
360
361  WIN_UNWRAP(PositionWindow);
362  fResult = (*pScreen->PositionWindow)(pWin, x, y);
363  WIN_WRAP(PositionWindow, winPositionWindowRootless);
364
365  winUpdateRgnRootless (pWin);
366
367  return fResult;
368}
369
370
371/* See Porting Layer Definition - p. 37 */
372/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
373
374Bool
375winChangeWindowAttributesRootless (WindowPtr pWin, unsigned long mask)
376{
377  Bool			fResult = FALSE;
378  ScreenPtr		pScreen = pWin->drawable.pScreen;
379  winScreenPriv(pScreen);
380
381#if CYGDEBUG
382  winTrace ("winChangeWindowAttributesRootless (%p)\n", pWin);
383#endif
384
385  WIN_UNWRAP(ChangeWindowAttributes);
386  fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
387  WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesRootless);
388
389  winUpdateRgnRootless (pWin);
390
391  return fResult;
392}
393
394
395/* See Porting Layer Definition - p. 37
396 * Also referred to as UnrealizeWindow
397 */
398
399Bool
400winUnmapWindowRootless (WindowPtr pWin)
401{
402  Bool			fResult = FALSE;
403  ScreenPtr		pScreen = pWin->drawable.pScreen;
404  winWindowPriv(pWin);
405  winScreenPriv(pScreen);
406
407#if CYGDEBUG
408  winTrace ("winUnmapWindowRootless (%p)\n", pWin);
409#endif
410
411  WIN_UNWRAP(UnrealizeWindow);
412  fResult = (*pScreen->UnrealizeWindow)(pWin);
413  WIN_WRAP(UnrealizeWindow, winUnmapWindowRootless);
414
415  if (pWinPriv->hRgn != NULL)
416    {
417      DeleteObject(pWinPriv->hRgn);
418      pWinPriv->hRgn = NULL;
419    }
420
421  winUpdateRgnRootless (pWin);
422
423  return fResult;
424}
425
426
427/* See Porting Layer Definition - p. 37
428 * Also referred to as RealizeWindow
429 */
430
431Bool
432winMapWindowRootless (WindowPtr pWin)
433{
434  Bool			fResult = FALSE;
435  ScreenPtr		pScreen = pWin->drawable.pScreen;
436  winScreenPriv(pScreen);
437
438#if CYGDEBUG
439  winTrace ("winMapWindowRootless (%p)\n", pWin);
440#endif
441
442  WIN_UNWRAP(RealizeWindow);
443  fResult = (*pScreen->RealizeWindow)(pWin);
444  WIN_WRAP(RealizeWindow, winMapWindowRootless);
445
446  winReshapeRootless (pWin);
447
448  winUpdateRgnRootless (pWin);
449
450  return fResult;
451}
452
453
454void
455winSetShapeRootless (WindowPtr pWin, int kind)
456{
457  ScreenPtr		pScreen = pWin->drawable.pScreen;
458  winScreenPriv(pScreen);
459
460#if CYGDEBUG
461  winTrace ("winSetShapeRootless (%p, %i)\n", pWin, kind);
462#endif
463
464  WIN_UNWRAP(SetShape);
465  (*pScreen->SetShape)(pWin, kind);
466  WIN_WRAP(SetShape, winSetShapeRootless);
467
468  winReshapeRootless (pWin);
469  winUpdateRgnRootless (pWin);
470
471  return;
472}
473
474
475/*
476 * Local function for adding a region to the Windows window region
477 */
478
479static
480int
481winAddRgn (WindowPtr pWin, pointer data)
482{
483  int		iX, iY, iWidth, iHeight, iBorder;
484  HRGN		hRgn = *(HRGN*)data;
485  HRGN		hRgnWin;
486  winWindowPriv(pWin);
487
488  /* If pWin is not Root */
489  if (pWin->parent != NULL)
490    {
491#if CYGDEBUG
492      winDebug ("winAddRgn ()\n");
493#endif
494      if (pWin->mapped)
495	{
496	  iBorder = wBorderWidth (pWin);
497
498	  iX = pWin->drawable.x - iBorder;
499	  iY = pWin->drawable.y - iBorder;
500
501	  iWidth = pWin->drawable.width + iBorder * 2;
502	  iHeight = pWin->drawable.height + iBorder * 2;
503
504	  hRgnWin = CreateRectRgn (0, 0, iWidth, iHeight);
505
506	  if (hRgnWin == NULL)
507	    {
508	      ErrorF ("winAddRgn - CreateRectRgn () failed\n");
509	      ErrorF ("  Rect %d %d %d %d\n",
510		      iX, iY, iX + iWidth, iY + iHeight);
511	    }
512
513	  if (pWinPriv->hRgn)
514	    {
515	      if (CombineRgn (hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND)
516		  == ERROR)
517		{
518		  ErrorF ("winAddRgn - CombineRgn () failed\n");
519		}
520	    }
521
522	  OffsetRgn (hRgnWin, iX, iY);
523
524	  if (CombineRgn (hRgn, hRgn, hRgnWin, RGN_OR) == ERROR)
525	    {
526	      ErrorF ("winAddRgn - CombineRgn () failed\n");
527	    }
528
529	  DeleteObject (hRgnWin);
530	}
531      return WT_DONTWALKCHILDREN;
532    }
533  else
534    {
535      return WT_WALKCHILDREN;
536    }
537}
538
539
540/*
541 * Local function to update the Windows window's region
542 */
543
544static
545void
546winUpdateRgnRootless (WindowPtr pWin)
547{
548  HRGN		hRgn = CreateRectRgn (0, 0, 0, 0);
549
550  if (hRgn != NULL)
551    {
552      WalkTree (pWin->drawable.pScreen, winAddRgn, &hRgn);
553      SetWindowRgn (winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen,
554		    hRgn, TRUE);
555    }
556  else
557    {
558      ErrorF ("winUpdateRgnRootless - CreateRectRgn failed.\n");
559    }
560}
561
562
563static
564void
565winReshapeRootless (WindowPtr pWin)
566{
567  int		nRects;
568  RegionRec	rrNewShape;
569  BoxPtr	pShape, pRects, pEnd;
570  HRGN		hRgn, hRgnRect;
571  winWindowPriv(pWin);
572
573#if CYGDEBUG
574  winDebug ("winReshapeRootless ()\n");
575#endif
576
577  /* Bail if the window is the root window */
578  if (pWin->parent == NULL)
579    return;
580
581  /* Bail if the window is not top level */
582  if (pWin->parent->parent != NULL)
583    return;
584
585  /* Free any existing window region stored in the window privates */
586  if (pWinPriv->hRgn != NULL)
587    {
588      DeleteObject (pWinPriv->hRgn);
589      pWinPriv->hRgn = NULL;
590    }
591
592  /* Bail if the window has no bounding region defined */
593  if (!wBoundingShape (pWin))
594    return;
595
596  RegionNull(&rrNewShape);
597  RegionCopy(&rrNewShape, wBoundingShape(pWin));
598  RegionTranslate(&rrNewShape, pWin->borderWidth,
599                   pWin->borderWidth);
600
601  nRects = RegionNumRects(&rrNewShape);
602  pShape = RegionRects(&rrNewShape);
603
604  if (nRects > 0)
605    {
606      /* Create initial empty Windows region */
607      hRgn = CreateRectRgn (0, 0, 0, 0);
608
609      /* Loop through all rectangles in the X region */
610      for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++)
611        {
612	  /* Create a Windows region for the X rectangle */
613	  hRgnRect = CreateRectRgn (pRects->x1, pRects->y1,
614				    pRects->x2, pRects->y2);
615	  if (hRgnRect == NULL)
616	    {
617	      ErrorF("winReshapeRootless - CreateRectRgn() failed\n");
618	    }
619
620	  /* Merge the Windows region with the accumulated region */
621	  if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR)
622	    {
623	      ErrorF("winReshapeRootless - CombineRgn() failed\n");
624	    }
625
626	  /* Delete the temporary Windows region */
627	  DeleteObject (hRgnRect);
628        }
629
630      /* Save a handle to the composite region in the window privates */
631      pWinPriv->hRgn = hRgn;
632    }
633
634  RegionUninit(&rrNewShape);
635
636  return;
637}
638