winwin32rootless.c revision 706f2543
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 *		Earle F. Philhower, III
30 *		Harold L Hunt II
31 */
32/*
33 * Look at hw/darwin/quartz/xpr/xprFrame.c and hw/darwin/quartz/cr/crFrame.c
34 */
35#ifdef HAVE_XWIN_CONFIG_H
36#include <xwin-config.h>
37#endif
38#include "win.h"
39#include <winuser.h>
40#define _WINDOWSWM_SERVER_
41#include <X11/extensions/windowswmstr.h>
42#include "dixevents.h"
43#include "winmultiwindowclass.h"
44#include <X11/Xatom.h>
45
46
47/*
48 * Constant defines
49 */
50
51#ifndef ULW_COLORKEY
52#define ULW_COLORKEY	0x00000001
53#endif
54#ifndef ULW_ALPHA
55#define ULW_ALPHA	0x00000002
56#endif
57#ifndef ULW_OPAQUE
58#define ULW_OPAQUE	0x00000004
59#endif
60#define AC_SRC_ALPHA	0x01
61
62/*
63 * Local function
64 */
65
66DEFINE_ATOM_HELPER(AtmWindowsWmNativeHwnd, WINDOWSWM_NATIVE_HWND)
67static void
68winMWExtWMSetNativeProperty (RootlessWindowPtr pFrame);
69
70/*
71 * Global variables
72 */
73
74Bool			g_fNoConfigureWindow = FALSE;
75
76/*
77 * Internal function to get the DIB format that is compatible with the screen
78 * Fixme: Share code with winshadgdi.c
79 */
80
81static
82Bool
83winMWExtWMQueryDIBFormat (win32RootlessWindowPtr pRLWinPriv, BITMAPINFOHEADER *pbmih)
84{
85  HBITMAP		hbmp;
86#if CYGMULTIWINDOW_DEBUG
87  LPDWORD		pdw = NULL;
88#endif
89
90  /* Create a memory bitmap compatible with the screen */
91  hbmp = CreateCompatibleBitmap (pRLWinPriv->hdcScreen, 1, 1);
92  if (hbmp == NULL)
93    {
94      ErrorF ("winMWExtWMQueryDIBFormat - CreateCompatibleBitmap failed\n");
95      return FALSE;
96    }
97
98  /* Initialize our bitmap info header */
99  ZeroMemory (pbmih, sizeof (BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD));
100  pbmih->biSize = sizeof (BITMAPINFOHEADER);
101
102  /* Get the biBitCount */
103  if (!GetDIBits (pRLWinPriv->hdcScreen,
104		  hbmp,
105		  0, 1,
106		  NULL,
107		  (BITMAPINFO*) pbmih,
108		  DIB_RGB_COLORS))
109    {
110      ErrorF ("winMWExtWMQueryDIBFormat - First call to GetDIBits failed\n");
111      DeleteObject (hbmp);
112      return FALSE;
113    }
114
115#if CYGMULTIWINDOW_DEBUG
116  /* Get a pointer to bitfields */
117  pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
118
119  winDebug ("winMWExtWMQueryDIBFormat - First call masks: %08x %08x %08x\n",
120	  (unsigned int)pdw[0], (unsigned int)pdw[1], (unsigned int)pdw[2]);
121#endif
122
123  /* Get optimal color table, or the optimal bitfields */
124  if (!GetDIBits (pRLWinPriv->hdcScreen,
125		  hbmp,
126		  0, 1,
127		  NULL,
128		  (BITMAPINFO*)pbmih,
129		  DIB_RGB_COLORS))
130    {
131      ErrorF ("winMWExtWMQueryDIBFormat - Second call to GetDIBits "
132	      "failed\n");
133      DeleteObject (hbmp);
134      return FALSE;
135    }
136
137  /* Free memory */
138  DeleteObject (hbmp);
139
140  return TRUE;
141}
142
143static HRGN
144winMWExtWMCreateRgnFromRegion (RegionPtr pShape)
145{
146  int		nRects;
147  BoxPtr	pRects, pEnd;
148  HRGN		hRgn, hRgnRect;
149
150  if (pShape == NULL) return NULL;
151
152  nRects = RegionNumRects(pShape);
153  pRects = RegionRects(pShape);
154
155  hRgn = CreateRectRgn (0, 0, 0, 0);
156  if (hRgn == NULL)
157    {
158      ErrorF ("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) "
159	      "failed: %d\n",
160	      0, 0, 0, 0, (int) GetLastError ());
161    }
162
163  /* Loop through all rectangles in the X region */
164  for (pEnd = pRects + nRects; pRects < pEnd; pRects++)
165    {
166      /* Create a Windows region for the X rectangle */
167      hRgnRect = CreateRectRgn (pRects->x1,
168				pRects->y1,
169				pRects->x2,
170				pRects->y2);
171      if (hRgnRect == NULL)
172	{
173	  ErrorF ("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) "
174		  "failed: %d\n",
175		  pRects->x1,
176		  pRects->y1,
177		  pRects->x2,
178		  pRects->y2,
179		  (int) GetLastError ());
180	}
181
182      /* Merge the Windows region with the accumulated region */
183      if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR)
184	{
185	  ErrorF ("winReshape - CombineRgn () failed: %d\n",
186		  (int) GetLastError ());
187	}
188
189      /* Delete the temporary Windows region */
190      DeleteObject (hRgnRect);
191    }
192
193  return hRgn;
194}
195
196static void
197InitWin32RootlessEngine (win32RootlessWindowPtr pRLWinPriv)
198{
199  pRLWinPriv->hdcScreen = GetDC (pRLWinPriv->hWnd);
200  pRLWinPriv->hdcShadow = CreateCompatibleDC (pRLWinPriv->hdcScreen);
201  pRLWinPriv->hbmpShadow = NULL;
202
203  /* Allocate bitmap info header */
204  pRLWinPriv->pbmihShadow = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
205							+ 256 * sizeof (RGBQUAD));
206  if (pRLWinPriv->pbmihShadow == NULL)
207    {
208      ErrorF ("InitWin32RootlessEngine - malloc () failed\n");
209      return;
210    }
211
212  /* Query the screen format */
213  winMWExtWMQueryDIBFormat (pRLWinPriv,
214				  pRLWinPriv->pbmihShadow);
215}
216
217Bool
218winMWExtWMCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen,
219			     int newX, int newY, RegionPtr pShape)
220{
221#define CLASS_NAME_LENGTH 512
222  Bool				fResult = TRUE;
223  win32RootlessWindowPtr	pRLWinPriv;
224  WNDCLASSEX			wc;
225  char				pszClass[CLASS_NAME_LENGTH], pszWindowID[12];
226  HICON				hIcon;
227  HICON				hIconSmall;
228  char				*res_name, *res_class, *res_role;
229  static int			s_iWindowID = 0;
230
231#if CYGMULTIWINDOW_DEBUG
232  winDebug ("winMWExtWMCreateFrame %d %d - %d %d\n",
233	  newX, newY, pFrame->width, pFrame->height);
234#endif
235
236  pRLWinPriv = (win32RootlessWindowPtr) malloc (sizeof (win32RootlessWindowRec));
237  pRLWinPriv->pFrame = pFrame;
238  pRLWinPriv->pfb = NULL;
239  pRLWinPriv->hbmpShadow = NULL;
240  pRLWinPriv->hdcShadow = NULL;
241  pRLWinPriv->hdcScreen = NULL;
242  pRLWinPriv->pbmihShadow = NULL;
243  pRLWinPriv->fResized = TRUE;
244  pRLWinPriv->fClose = FALSE;
245  pRLWinPriv->fRestackingNow = FALSE;
246  pRLWinPriv->fDestroyed = FALSE;
247  pRLWinPriv->fMovingOrSizing = FALSE;
248
249  // Store the implementation private frame ID
250  pFrame->wid = (RootlessFrameID) pRLWinPriv;
251
252  winSelectIcons(pFrame->win, &hIcon, &hIconSmall);
253
254  /* Set standard class name prefix so we can identify window easily */
255  strncpy (pszClass, WINDOW_CLASS_X, sizeof(pszClass));
256
257  if (winMultiWindowGetClassHint (pFrame->win, &res_name, &res_class))
258    {
259      strncat (pszClass, "-", 1);
260      strncat (pszClass, res_name, CLASS_NAME_LENGTH - strlen (pszClass));
261      strncat (pszClass, "-", 1);
262      strncat (pszClass, res_class, CLASS_NAME_LENGTH - strlen (pszClass));
263
264      /* Check if a window class is provided by the WM_WINDOW_ROLE property,
265       * if not use the WM_CLASS information.
266       * For further information see:
267       * http://tronche.com/gui/x/icccm/sec-5.html
268       */
269      if (winMultiWindowGetWindowRole (pFrame->win, &res_role) )
270	{
271	  strcat (pszClass, "-");
272	  strcat (pszClass, res_role);
273	  free (res_role);
274	}
275
276      free (res_name);
277      free (res_class);
278    }
279
280  /* Add incrementing window ID to make unique class name */
281  snprintf (pszWindowID, sizeof(pszWindowID), "-%x", s_iWindowID++);
282  pszWindowID[sizeof(pszWindowID)-1] = 0;
283  strcat (pszClass, pszWindowID);
284
285#if CYGMULTIWINDOW_DEBUG
286  winDebug ("winCreateWindowsWindow - Creating class: %s\n", pszClass);
287#endif
288
289  /* Setup our window class */
290  wc.cbSize = sizeof(wc);
291  wc.style = CS_HREDRAW | CS_VREDRAW;
292  wc.lpfnWndProc = winMWExtWMWindowProc;
293  wc.cbClsExtra = 0;
294  wc.cbWndExtra = 0;
295  wc.hInstance = g_hInstance;
296  wc.hIcon = hIcon;
297  wc.hIconSm = hIconSmall;
298  wc.hCursor = 0;
299  wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
300  wc.lpszMenuName = NULL;
301  wc.lpszClassName = pszClass;
302  RegisterClassEx (&wc);
303
304  /* Create the window */
305  g_fNoConfigureWindow = TRUE;
306  pRLWinPriv->hWnd = CreateWindowExA (WS_EX_TOOLWINDOW,		/* Extended styles */
307				      pszClass,			/* Class name */
308				      WINDOW_TITLE_X,		/* Window name */
309				      WS_POPUP | WS_CLIPCHILDREN,
310				      newX,			/* Horizontal position */
311				      newY,			/* Vertical position */
312				      pFrame->width,		/* Right edge */
313				      pFrame->height,		/* Bottom edge */
314				      (HWND) NULL,		/* No parent or owner window */
315				      (HMENU) NULL,		/* No menu */
316				      GetModuleHandle (NULL),	/* Instance handle */
317				      pRLWinPriv);		/* ScreenPrivates */
318  if (pRLWinPriv->hWnd == NULL)
319    {
320      ErrorF ("winMWExtWMCreateFrame - CreateWindowExA () failed: %d\n",
321	      (int) GetLastError ());
322      fResult = FALSE;
323    }
324
325#if CYGMULTIWINDOW_DEBUG
326  winDebug ("winMWExtWMCreateFrame - ShowWindow\n");
327#endif
328
329  //ShowWindow (pRLWinPriv->hWnd, SW_SHOWNOACTIVATE);
330  g_fNoConfigureWindow = FALSE;
331
332  if (pShape != NULL)
333    {
334      winMWExtWMReshapeFrame (pFrame->wid, pShape);
335    }
336
337#if CYGMULTIWINDOW_DEBUG
338  winDebug ("winMWExtWMCreateFrame - (%08x) %08x\n",
339	  (int) pFrame->wid, (int) pRLWinPriv->hWnd);
340#if 0
341  {
342   WindowPtr		pWin2 = NULL;
343   win32RootlessWindowPtr pRLWinPriv2 = NULL;
344
345   /* Check if the Windows window property for our X window pointer is valid */
346   if ((pWin2 = (WindowPtr)GetProp (pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL)
347     {
348       pRLWinPriv2 = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin2, FALSE);
349     }
350   winDebug ("winMWExtWMCreateFrame2 (%08x) %08x\n",
351	   pRLWinPriv2, pRLWinPriv2->hWnd);
352   if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd)
353     {
354       winDebug ("Error param missmatch\n");
355     }
356 }
357#endif
358#endif
359
360  winMWExtWMSetNativeProperty (pFrame);
361
362  return fResult;
363}
364
365void
366winMWExtWMDestroyFrame (RootlessFrameID wid)
367{
368  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
369  HICON			hiconClass;
370  HICON			hiconSmClass;
371  HMODULE		hInstance;
372  int			iReturn;
373  char			pszClass[CLASS_NAME_LENGTH];
374
375#if CYGMULTIWINDOW_DEBUG
376  winDebug ("winMWExtWMDestroyFrame (%08x) %08x\n",
377	  (int) pRLWinPriv, (int) pRLWinPriv->hWnd);
378#if 0
379 {
380   WindowPtr		pWin2 = NULL;
381   win32RootlessWindowPtr pRLWinPriv2 = NULL;
382
383   /* Check if the Windows window property for our X window pointer is valid */
384   if ((pWin2 = (WindowPtr)GetProp (pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL)
385     {
386       pRLWinPriv2 = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin2, FALSE);
387     }
388   winDebug ("winMWExtWMDestroyFrame2 (%08x) %08x\n",
389	   pRLWinPriv2, pRLWinPriv2->hWnd);
390   if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd)
391     {
392       winDebug ("Error param missmatch\n");
393       *(int*)0 = 1;//raise exseption
394     }
395 }
396#endif
397#endif
398
399  /* Store the info we need to destroy after this window is gone */
400  hInstance = (HINSTANCE) GetClassLongPtr (pRLWinPriv->hWnd, GCLP_HMODULE);
401  hiconClass = (HICON) GetClassLongPtr (pRLWinPriv->hWnd, GCLP_HICON);
402  hiconSmClass = (HICON) GetClassLongPtr (pRLWinPriv->hWnd, GCLP_HICONSM);
403  iReturn = GetClassName (pRLWinPriv->hWnd, pszClass, CLASS_NAME_LENGTH);
404
405  pRLWinPriv->fClose = TRUE;
406  pRLWinPriv->fDestroyed = TRUE;
407
408  /* Destroy the Windows window */
409  DestroyWindow (pRLWinPriv->hWnd);
410
411  /* Only if we were able to get the name */
412  if (iReturn)
413    {
414#if CYGMULTIWINDOW_DEBUG
415      winDebug ("winMWExtWMDestroyFrame - Unregistering %s: ", pszClass);
416#endif
417      iReturn = UnregisterClass (pszClass, hInstance);
418
419#if CYGMULTIWINDOW_DEBUG
420      winDebug ("winMWExtWMDestroyFramew - %d Deleting Icon: ", iReturn);
421#endif
422
423      winDestroyIcon(hiconClass);
424      winDestroyIcon(hiconSmClass);
425    }
426
427#if CYGMULTIWINDOW_DEBUG
428  winDebug ("winMWExtWMDestroyFrame - done\n");
429#endif
430}
431
432void
433winMWExtWMMoveFrame (RootlessFrameID wid, ScreenPtr pScreen, int iNewX, int iNewY)
434{
435  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
436  RECT rcNew;
437  DWORD dwExStyle;
438  DWORD dwStyle;
439  int iX, iY, iWidth, iHeight;
440
441#if CYGMULTIWINDOW_DEBUG
442  winDebug ("winMWExtWMMoveFrame (%08x) (%d %d)\n", (int) pRLWinPriv, iNewX, iNewY);
443#endif
444
445  /* Get the Windows window style and extended style */
446  dwExStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE);
447  dwStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE);
448
449  /* Get the X and Y location of the X window */
450  iX = iNewX + GetSystemMetrics (SM_XVIRTUALSCREEN);
451  iY = iNewY + GetSystemMetrics (SM_YVIRTUALSCREEN);
452
453  /* Get the height and width of the X window */
454  iWidth = pRLWinPriv->pFrame->width;
455  iHeight = pRLWinPriv->pFrame->height;
456
457  /* Store the origin, height, and width in a rectangle structure */
458  SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight);
459
460#ifdef CYGMULTIWINDOW_DEBUG
461          winDebug("\tWindow {%d, %d, %d, %d}, {%d, %d}\n",
462              rcNew.left, rcNew.top, rcNew.right, rcNew.bottom,
463              rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
464#endif
465  /*
466   * Calculate the required size of the Windows window rectangle,
467   * given the size of the Windows window client area.
468   */
469  AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle);
470
471#ifdef CYGMULTIWINDOW_DEBUG
472          winDebug("\tAdjusted {%d, %d, %d, %d}, {%d, %d}\n",
473              rcNew.left, rcNew.top, rcNew.right, rcNew.bottom,
474              rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
475#endif
476  g_fNoConfigureWindow = TRUE;
477  SetWindowPos (pRLWinPriv->hWnd, NULL, rcNew.left, rcNew.top, 0, 0,
478		SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
479  g_fNoConfigureWindow = FALSE;
480#if CYGMULTIWINDOW_DEBUG
481  winDebug ("winMWExtWMMoveFrame (%08x) done\n", (int) pRLWinPriv);
482#endif
483}
484
485void
486winMWExtWMResizeFrame (RootlessFrameID wid, ScreenPtr pScreen,
487			     int iNewX, int iNewY,
488			     unsigned int uiNewWidth, unsigned int uiNewHeight,
489			     unsigned int uiGravity)
490{
491  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
492  RECT rcNew;
493  RECT rcOld;
494  DWORD dwExStyle;
495  DWORD dwStyle;
496  int iX, iY;
497
498#if CYGMULTIWINDOW_DEBUG
499  winDebug ("winMWExtWMResizeFrame (%08x) (%d %d)-(%d %d)\n",
500	  (int) pRLWinPriv, iNewX, iNewY, uiNewWidth, uiNewHeight);
501#endif
502
503  pRLWinPriv->fResized = TRUE;
504
505  /* Get the Windows window style and extended style */
506  dwExStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE);
507  dwStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE);
508
509  /* Get the X and Y location of the X window */
510  iX = iNewX + GetSystemMetrics (SM_XVIRTUALSCREEN);
511  iY = iNewY + GetSystemMetrics (SM_YVIRTUALSCREEN);
512
513  /* Store the origin, height, and width in a rectangle structure */
514  SetRect (&rcNew, iX, iY, iX + uiNewWidth, iY + uiNewHeight);
515
516  /*
517   * Calculate the required size of the Windows window rectangle,
518   * given the size of the Windows window client area.
519   */
520  AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle);
521
522  /* Get a rectangle describing the old Windows window */
523  GetWindowRect (pRLWinPriv->hWnd, &rcOld);
524
525  /* Check if the old rectangle and new rectangle are the same */
526  if (!EqualRect (&rcNew, &rcOld))
527    {
528
529      g_fNoConfigureWindow = TRUE;
530      MoveWindow (pRLWinPriv->hWnd,
531		  rcNew.left, rcNew.top,
532		  rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
533		  TRUE);
534      g_fNoConfigureWindow = FALSE;
535    }
536}
537
538void
539winMWExtWMRestackFrame (RootlessFrameID wid, RootlessFrameID nextWid)
540{
541  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
542  win32RootlessWindowPtr pRLNextWinPriv = (win32RootlessWindowPtr) nextWid;
543  winScreenPriv(pRLWinPriv->pFrame->win->drawable.pScreen);
544  winScreenInfo *pScreenInfo = NULL;
545  DWORD dwCurrentProcessID = GetCurrentProcessId ();
546  DWORD dwWindowProcessID = 0;
547  HWND hWnd;
548  Bool fFirst = TRUE;
549  Bool fNeedRestack = TRUE;
550#if CYGMULTIWINDOW_DEBUG
551  winDebug ("winMWExtWMRestackFrame (%08x)\n", (int) pRLWinPriv);
552#endif
553
554  if (pScreenPriv->fRestacking) return;
555
556  if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
557
558  pRLWinPriv->fRestackingNow = TRUE;
559
560  /* Show window */
561  if(!IsWindowVisible (pRLWinPriv->hWnd))
562    ShowWindow (pRLWinPriv->hWnd, SW_SHOWNOACTIVATE);
563
564  if (pRLNextWinPriv == NULL)
565    {
566#if CYGMULTIWINDOW_DEBUG
567      winDebug ("Win %08x is top\n", pRLWinPriv);
568#endif
569      pScreenPriv->widTop = wid;
570      SetWindowPos (pRLWinPriv->hWnd, HWND_TOP,
571		    0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
572    }
573  else if (winIsInternalWMRunning(pScreenInfo))
574    {
575      /* using mulwinidow wm */
576#if CYGMULTIWINDOW_DEBUG
577      winDebug ("Win %08x is not top\n", pRLWinPriv);
578#endif
579      for (hWnd = GetNextWindow (pRLWinPriv->hWnd, GW_HWNDPREV);
580	   fNeedRestack && hWnd != NULL;
581	   hWnd = GetNextWindow (hWnd, GW_HWNDPREV))
582	{
583	  GetWindowThreadProcessId (hWnd, &dwWindowProcessID);
584
585	  if ((dwWindowProcessID == dwCurrentProcessID)
586	      && GetProp (hWnd, WIN_WINDOW_PROP))
587	    {
588	      if (hWnd == pRLNextWinPriv->hWnd)
589		{
590		  /* Enable interleave X window and Windows window */
591		  if (!fFirst)
592		    {
593#if CYGMULTIWINDOW_DEBUG
594		      winDebug ("raise: Insert after Win %08x\n", pRLNextWinPriv);
595#endif
596		      SetWindowPos (pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
597				    0, 0, 0, 0,
598				    SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
599		    }
600		  else
601		    {
602#if CYGMULTIWINDOW_DEBUG
603		      winDebug ("No change\n");
604#endif
605		    }
606		  fNeedRestack = FALSE;
607		  break;
608		}
609	      if (fFirst) fFirst = FALSE;
610	    }
611	}
612
613      for (hWnd = GetNextWindow (pRLWinPriv->hWnd, GW_HWNDNEXT);
614	   fNeedRestack && hWnd != NULL;
615	   hWnd = GetNextWindow (hWnd, GW_HWNDNEXT))
616	{
617	  GetWindowThreadProcessId (hWnd, &dwWindowProcessID);
618
619	  if ((dwWindowProcessID == dwCurrentProcessID)
620	      && GetProp (hWnd, WIN_WINDOW_PROP))
621	    {
622	      if (hWnd == pRLNextWinPriv->hWnd)
623		{
624#if CYGMULTIWINDOW_DEBUG
625		  winDebug ("lower: Insert after Win %08x\n", pRLNextWinPriv);
626#endif
627		  SetWindowPos (pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
628				0, 0, 0, 0,
629				SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
630		  fNeedRestack = FALSE;
631		  break;
632		}
633	    }
634	}
635    }
636  else
637    {
638      /* using general wm like twm, wmaker etc.
639	 Interleave X window and Windows window will cause problem. */
640      SetWindowPos (pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
641		    0, 0, 0, 0,
642		    SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
643#if 0
644#endif
645    }
646#if CYGMULTIWINDOW_DEBUG
647  winDebug ("winMWExtWMRestackFrame - done (%08x)\n", (int) pRLWinPriv);
648#endif
649
650  pRLWinPriv->fRestackingNow = FALSE;
651}
652
653void
654winMWExtWMReshapeFrame (RootlessFrameID wid, RegionPtr pShape)
655{
656  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
657  HRGN hRgn, hRgnWindow, hRgnClient;
658  RECT rcWindow, rcClient;
659#if CYGMULTIWINDOW_DEBUG
660  winDebug ("winMWExtWMReshapeFrame (%08x)\n", (int) pRLWinPriv);
661#endif
662
663  hRgn = winMWExtWMCreateRgnFromRegion (pShape);
664
665  /* Create region for non-client area */
666  GetWindowRect (pRLWinPriv->hWnd, &rcWindow);
667  GetClientRect (pRLWinPriv->hWnd, &rcClient);
668  MapWindowPoints (pRLWinPriv->hWnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2);
669  OffsetRgn (hRgn, rcClient.left - rcWindow.left, rcClient.top - rcWindow.top);
670  OffsetRect (&rcClient, -rcWindow.left, -rcWindow.top);
671  OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
672  hRgnWindow = CreateRectRgnIndirect (&rcWindow);
673  hRgnClient = CreateRectRgnIndirect (&rcClient);
674  CombineRgn (hRgnWindow, hRgnWindow, hRgnClient, RGN_DIFF);
675  CombineRgn (hRgn, hRgnWindow, hRgn, RGN_OR);
676
677
678  SetWindowRgn (pRLWinPriv->hWnd, hRgn, TRUE);
679
680  DeleteObject (hRgnWindow);
681  DeleteObject (hRgnClient);
682}
683
684void
685winMWExtWMUnmapFrame (RootlessFrameID wid)
686{
687  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
688#if CYGMULTIWINDOW_DEBUG
689  winDebug ("winMWExtWMUnmapFrame (%08x)\n", (int) pRLWinPriv);
690#endif
691
692  g_fNoConfigureWindow = TRUE;
693  //ShowWindow (pRLWinPriv->hWnd, SW_MINIMIZE);
694  ShowWindow (pRLWinPriv->hWnd, SW_HIDE);
695  g_fNoConfigureWindow = FALSE;
696}
697
698/*
699 * Fixme: Code sharing with winshadgdi.c and other engine support
700 */
701void
702winMWExtWMStartDrawing (RootlessFrameID wid, char **pixelData, int *bytesPerRow)
703{
704  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
705  winPrivScreenPtr	pScreenPriv = NULL;
706  winScreenInfo		*pScreenInfo = NULL;
707  ScreenPtr		pScreen = NULL;
708  DIBSECTION		dibsection;
709  Bool			fReturn = TRUE;
710  HDC			hdcNew;
711  HBITMAP		hbmpNew;
712#if CYGMULTIWINDOW_DEBUG
713  winDebug ("winMWExtWMStartDrawing (%08x) %08x\n", (int) pRLWinPriv, pRLWinPriv->fDestroyed);
714#endif
715
716  if (!pRLWinPriv->fDestroyed)
717    {
718      pScreen = pRLWinPriv->pFrame->win->drawable.pScreen;
719      if (pScreen) pScreenPriv = winGetScreenPriv(pScreen);
720      if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
721
722#if CYGMULTIWINDOW_DEBUG
723      winDebug ("\tpScreenPriv %08X\n", (int) pScreenPriv);
724      winDebug ("\tpScreenInfo %08X\n", (int) pScreenInfo);
725      winDebug ("\t(%d, %d)\n", (int)pRLWinPriv->pFrame->width,
726		(int) pRLWinPriv->pFrame->height);
727#endif
728      if (pRLWinPriv->hdcScreen == NULL)
729	{
730	  InitWin32RootlessEngine (pRLWinPriv);
731	}
732
733      if (pRLWinPriv->fResized)
734	{
735          /* width * bpp must be multiple of 4 to match 32bit alignment */
736	  int stridesize;
737	  int misalignment;
738
739	  pRLWinPriv->pbmihShadow->biWidth = pRLWinPriv->pFrame->width;
740	  pRLWinPriv->pbmihShadow->biHeight = -pRLWinPriv->pFrame->height;
741
742	  stridesize = pRLWinPriv->pFrame->width * (pScreenInfo->dwBPP >> 3);
743	  misalignment = stridesize & 3;
744	  if (misalignment != 0)
745	  {
746	    stridesize += 4 - misalignment;
747	    pRLWinPriv->pbmihShadow->biWidth = stridesize / (pScreenInfo->dwBPP >> 3);
748	    winDebug("\tresizing to %d (was %d)\n",
749		    pRLWinPriv->pbmihShadow->biWidth, pRLWinPriv->pFrame->width);
750	  }
751
752	  hdcNew = CreateCompatibleDC (pRLWinPriv->hdcScreen);
753	  /* Create a DI shadow bitmap with a bit pointer */
754	  hbmpNew = CreateDIBSection (pRLWinPriv->hdcScreen,
755				      (BITMAPINFO *) pRLWinPriv->pbmihShadow,
756				      DIB_RGB_COLORS,
757				      (VOID**) &pRLWinPriv->pfb,
758				      NULL,
759				      0);
760	  if (hbmpNew == NULL || pRLWinPriv->pfb == NULL)
761	    {
762	      ErrorF ("winMWExtWMStartDrawing - CreateDIBSection failed\n");
763	      //return FALSE;
764	    }
765	  else
766	    {
767#if CYGMULTIWINDOW_DEBUG
768	      winDebug ("winMWExtWMStartDrawing - Shadow buffer allocated\n");
769#endif
770	    }
771
772	  /* Get information about the bitmap that was allocated */
773	  GetObject (hbmpNew, sizeof (dibsection), &dibsection);
774
775#if CYGMULTIWINDOW_DEBUG
776	  /* Print information about bitmap allocated */
777	  winDebug ("winMWExtWMStartDrawing - Dibsection width: %d height: %d "
778		    "depth: %d size image: %d\n",
779		    (unsigned int)dibsection.dsBmih.biWidth,
780		    (unsigned int)dibsection.dsBmih.biHeight,
781		    (unsigned int)dibsection.dsBmih.biBitCount,
782		    (unsigned int)dibsection.dsBmih.biSizeImage);
783#endif
784
785	  /* Select the shadow bitmap into the shadow DC */
786	  SelectObject (hdcNew, hbmpNew);
787
788#if CYGMULTIWINDOW_DEBUG
789	  winDebug ("winMWExtWMStartDrawing - Attempting a shadow blit\n");
790#endif
791
792	  /* Blit from the old shadow to the new shadow */
793	  fReturn = BitBlt (hdcNew,
794			    0, 0,
795			    pRLWinPriv->pFrame->width, pRLWinPriv->pFrame->height,
796			    pRLWinPriv->hdcShadow,
797			    0, 0,
798			    SRCCOPY);
799	  if (fReturn)
800	    {
801#if CYGMULTIWINDOW_DEBUG
802	      winDebug ("winMWExtWMStartDrawing - Shadow blit success\n");
803#endif
804	    }
805	  else
806	    {
807	      ErrorF ("winMWExtWMStartDrawing - Shadow blit failure\n");
808	    }
809
810	  /* Look for height weirdness */
811	  if (dibsection.dsBmih.biHeight < 0)
812	    {
813	      /* FIXME: Figure out why biHeight is sometimes negative */
814	      ErrorF ("winMWExtWMStartDrawing - WEIRDNESS - "
815                  "biHeight still negative: %d\n",
816                  (int) dibsection.dsBmih.biHeight);
817	      ErrorF ("winMWExtWMStartDrawing - WEIRDNESS - "
818                  "Flipping biHeight sign\n");
819	      dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
820	    }
821
822	  pRLWinPriv->dwWidthBytes = dibsection.dsBm.bmWidthBytes;
823
824#if CYGMULTIWINDOW_DEBUG
825	  winDebug ("winMWExtWMStartDrawing - bytesPerRow: %d\n",
826		    (unsigned int)dibsection.dsBm.bmWidthBytes);
827#endif
828
829	  /* Free the old shadow bitmap */
830	  DeleteObject (pRLWinPriv->hdcShadow);
831	  DeleteObject (pRLWinPriv->hbmpShadow);
832
833	  pRLWinPriv->hdcShadow = hdcNew;
834	  pRLWinPriv->hbmpShadow = hbmpNew;
835
836	  pRLWinPriv->fResized = FALSE;
837#if CYGMULTIWINDOW_DEBUG && FALSE
838	  winDebug ("winMWExtWMStartDrawing - 0x%08x %d\n",
839		(unsigned int)pRLWinPriv->pfb,
840		(unsigned int)dibsection.dsBm.bmWidthBytes);
841#endif
842	}
843    }
844  else
845    {
846      ErrorF ("winMWExtWMStartDrawing - Already window was destroyed \n");
847    }
848#if CYGMULTIWINDOW_DEBUG
849  winDebug ("winMWExtWMStartDrawing - done (0x%08x) 0x%08x %d\n",
850	    (int) pRLWinPriv,
851	    (unsigned int)pRLWinPriv->pfb, (unsigned int)pRLWinPriv->dwWidthBytes);
852#endif
853  *pixelData = pRLWinPriv->pfb;
854  *bytesPerRow = pRLWinPriv->dwWidthBytes;
855}
856
857void
858winMWExtWMStopDrawing (RootlessFrameID wid, Bool fFlush)
859{
860#if 0
861  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
862  BLENDFUNCTION bfBlend;
863  SIZE szWin;
864  POINT ptSrc;
865#if CYGMULTIWINDOW_DEBUG || TRUE
866  winDebug ("winMWExtWMStopDrawing (%08x)\n", pRLWinPriv);
867#endif
868  szWin.cx = pRLWinPriv->dwWidth;
869  szWin.cy = pRLWinPriv->dwHeight;
870  ptSrc.x = 0;
871  ptSrc.y = 0;
872  bfBlend.BlendOp = AC_SRC_OVER;
873  bfBlend.BlendFlags = 0;
874  bfBlend.SourceConstantAlpha = 255;
875  bfBlend.AlphaFormat = AC_SRC_ALPHA;
876
877  if (!UpdateLayeredWindow (pRLWinPriv->hWnd,
878			    NULL, NULL, &szWin,
879			    pRLWinPriv->hdcShadow, &ptSrc,
880			    0, &bfBlend, ULW_ALPHA))
881    {
882      ErrorF ("winMWExtWMStopDrawing - UpdateLayeredWindow failed\n");
883    }
884#endif
885}
886
887void
888winMWExtWMUpdateRegion (RootlessFrameID wid, RegionPtr pDamage)
889{
890  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
891#if 0
892  BLENDFUNCTION bfBlend;
893  SIZE szWin;
894  POINT ptSrc;
895#endif
896#if CYGMULTIWINDOW_DEBUG && 0
897  winDebug ("winMWExtWMUpdateRegion (%08x)\n", pRLWinPriv);
898#endif
899#if 0
900  szWin.cx = pRLWinPriv->dwWidth;
901  szWin.cy = pRLWinPriv->dwHeight;
902  ptSrc.x = 0;
903  ptSrc.y = 0;
904  bfBlend.BlendOp = AC_SRC_OVER;
905  bfBlend.BlendFlags = 0;
906  bfBlend.SourceConstantAlpha = 255;
907  bfBlend.AlphaFormat = AC_SRC_ALPHA;
908
909  if (!UpdateLayeredWindow (pRLWinPriv->hWnd,
910			    NULL, NULL, &szWin,
911			    pRLWinPriv->hdcShadow, &ptSrc,
912			    0, &bfBlend, ULW_ALPHA))
913    {
914      LPVOID lpMsgBuf;
915
916      /* Display a fancy error message */
917      FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
918		     FORMAT_MESSAGE_FROM_SYSTEM |
919		     FORMAT_MESSAGE_IGNORE_INSERTS,
920		     NULL,
921		     GetLastError (),
922		     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
923		     (LPTSTR) &lpMsgBuf,
924		     0, NULL);
925
926      ErrorF ("winMWExtWMUpdateRegion - UpdateLayeredWindow failed: %s\n",
927	      (LPSTR)lpMsgBuf);
928      LocalFree (lpMsgBuf);
929    }
930#endif
931  if (!g_fNoConfigureWindow) UpdateWindow (pRLWinPriv->hWnd);
932}
933
934void
935winMWExtWMDamageRects (RootlessFrameID wid, int nCount, const BoxRec *pRects,
936			     int shift_x, int shift_y)
937{
938  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
939  const BoxRec *pEnd;
940#if CYGMULTIWINDOW_DEBUG && 0
941  winDebug ("winMWExtWMDamageRects (%08x, %d, %08x, %d, %d)\n",
942	    pRLWinPriv, nCount, pRects, shift_x, shift_y);
943#endif
944
945  for (pEnd = pRects + nCount; pRects < pEnd; pRects++) {
946        RECT rcDmg;
947        rcDmg.left = pRects->x1 + shift_x;
948        rcDmg.top = pRects->y1 + shift_y;
949        rcDmg.right = pRects->x2 + shift_x;
950        rcDmg.bottom = pRects->y2 + shift_y;
951
952	InvalidateRect (pRLWinPriv->hWnd, &rcDmg, FALSE);
953    }
954}
955
956void
957winMWExtWMRootlessSwitchWindow (RootlessWindowPtr pFrame, WindowPtr oldWin)
958{
959  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid;
960#if CYGMULTIWINDOW_DEBUG
961  winDebug ("winMWExtWMRootlessSwitchWindow (%08x) %08x\n",
962	    (int) pRLWinPriv, (int) pRLWinPriv->hWnd);
963#endif
964  pRLWinPriv->pFrame = pFrame;
965  pRLWinPriv->fResized = TRUE;
966
967  /* Set the window extended style flags */
968  SetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
969
970  /* Set the window standard style flags */
971  SetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE,
972		    WS_POPUP | WS_CLIPCHILDREN);
973
974  DeleteProperty (serverClient, oldWin, AtmWindowsWmNativeHwnd ());
975  winMWExtWMSetNativeProperty (pFrame);
976#if CYGMULTIWINDOW_DEBUG
977#if 0
978 {
979   WindowPtr		pWin2 = NULL;
980   win32RootlessWindowPtr pRLWinPriv2 = NULL;
981
982   /* Check if the Windows window property for our X window pointer is valid */
983   if ((pWin2 = (WindowPtr)GetProp (pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL)
984     {
985       pRLWinPriv2 = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin2, FALSE);
986     }
987   winDebug ("winMWExtWMSwitchFrame2 (%08x) %08x\n",
988	   pRLWinPriv2, pRLWinPriv2->hWnd);
989   if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd)
990     {
991       winDebug ("Error param missmatch\n");
992     }
993 }
994#endif
995#endif
996}
997
998void
999winMWExtWMCopyBytes (unsigned int width, unsigned int height,
1000			   const void *src, unsigned int srcRowBytes,
1001			   void *dst, unsigned int dstRowBytes)
1002{
1003#if CYGMULTIWINDOW_DEBUG
1004  winDebug ("winMWExtWMCopyBytes - Not implemented\n");
1005#endif
1006}
1007
1008void
1009winMWExtWMCopyWindow (RootlessFrameID wid, int nDstRects, const BoxRec *pDstRects,
1010			    int nDx, int nDy)
1011{
1012  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
1013  const BoxRec *pEnd;
1014  RECT rcDmg;
1015#if CYGMULTIWINDOW_DEBUG
1016  winDebug ("winMWExtWMCopyWindow (%08x, %d, %08x, %d, %d)\n",
1017	  (int) pRLWinPriv, nDstRects, (int) pDstRects, nDx, nDy);
1018#endif
1019
1020  for (pEnd = pDstRects + nDstRects; pDstRects < pEnd; pDstRects++)
1021    {
1022#if CYGMULTIWINDOW_DEBUG
1023      winDebug ("BitBlt (%d, %d, %d, %d) (%d, %d)\n",
1024	      pDstRects->x1, pDstRects->y1,
1025	      pDstRects->x2 - pDstRects->x1,
1026	      pDstRects->y2 - pDstRects->y1,
1027	      pDstRects->x1 + nDx,
1028	      pDstRects->y1 + nDy);
1029#endif
1030
1031      if (!BitBlt (pRLWinPriv->hdcShadow,
1032		   pDstRects->x1, pDstRects->y1,
1033		   pDstRects->x2 - pDstRects->x1,
1034		   pDstRects->y2 - pDstRects->y1,
1035		   pRLWinPriv->hdcShadow,
1036		   pDstRects->x1 + nDx,  pDstRects->y1 + nDy,
1037		   SRCCOPY))
1038	{
1039	  ErrorF ("winMWExtWMCopyWindow - BitBlt failed.\n");
1040	}
1041
1042      rcDmg.left = pDstRects->x1;
1043      rcDmg.top = pDstRects->y1;
1044      rcDmg.right = pDstRects->x2;
1045      rcDmg.bottom = pDstRects->y2;
1046
1047      InvalidateRect (pRLWinPriv->hWnd, &rcDmg, FALSE);
1048    }
1049#if CYGMULTIWINDOW_DEBUG
1050  winDebug ("winMWExtWMCopyWindow - done\n");
1051#endif
1052}
1053
1054
1055/*
1056 * winMWExtWMSetNativeProperty
1057 */
1058
1059static void
1060winMWExtWMSetNativeProperty (RootlessWindowPtr pFrame)
1061{
1062  win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid;
1063  long lData;
1064
1065  /* FIXME: move this to WindowsWM extension */
1066
1067  lData = (long) pRLWinPriv->hWnd;
1068  dixChangeWindowProperty(serverClient, pFrame->win, AtmWindowsWmNativeHwnd(),
1069			  XA_INTEGER, 32, PropModeReplace, 1, &lData, TRUE);
1070}
1071