1/*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *Copyright (C) Colin Harrison 2005-2008
4 *
5 *Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 *"Software"), to deal in the Software without restriction, including
8 *without limitation the rights to use, copy, modify, merge, publish,
9 *distribute, sublicense, and/or sell copies of the Software, and to
10 *permit persons to whom the Software is furnished to do so, subject to
11 *the following conditions:
12 *
13 *The above copyright notice and this permission notice shall be
14 *included in all copies or substantial portions of the Software.
15 *
16 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *Except as contained in this notice, the name of the XFree86 Project
25 *shall not be used in advertising or otherwise to promote the sale, use
26 *or other dealings in this Software without prior written authorization
27 *from the XFree86 Project.
28 *
29 * Authors:	Kensuke Matsuzaki
30 *		Earle F. Philhower, III
31 *		Harold L Hunt II
32 *              Colin Harrison
33 */
34
35#ifdef HAVE_XWIN_CONFIG_H
36#include <xwin-config.h>
37#endif
38#include "win.h"
39#include "dixevents.h"
40#include "winmultiwindowclass.h"
41
42/*
43 * Prototypes for local functions
44 */
45
46void
47winCreateWindowsWindow (WindowPtr pWin);
48
49static void
50winDestroyWindowsWindow (WindowPtr pWin);
51
52static void
53winUpdateWindowsWindow (WindowPtr pWin);
54
55static void
56winFindWindow (pointer value, XID id, pointer cdata);
57
58static
59void winInitMultiWindowClass(void)
60{
61  static wATOM atomXWinClass=0;
62  WNDCLASSEX wcx;
63
64  if (atomXWinClass==0)
65  {
66    /* Setup our window class */
67    wcx.cbSize=sizeof(WNDCLASSEX);
68    wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0);
69    wcx.lpfnWndProc = winTopLevelWindowProc;
70    wcx.cbClsExtra = 0;
71    wcx.cbWndExtra = 0;
72    wcx.hInstance = g_hInstance;
73    wcx.hIcon = g_hIconX;
74    wcx.hCursor = 0;
75    wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
76    wcx.lpszMenuName = NULL;
77    wcx.lpszClassName = WINDOW_CLASS_X;
78    wcx.hIconSm = g_hSmallIconX;
79
80#if CYGMULTIWINDOW_DEBUG
81    ErrorF ("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X);
82#endif
83
84    atomXWinClass = RegisterClassEx (&wcx);
85  }
86}
87
88/*
89 * CreateWindow - See Porting Layer Definition - p. 37
90 */
91
92Bool
93winCreateWindowMultiWindow (WindowPtr pWin)
94{
95  Bool			fResult = TRUE;
96  ScreenPtr		pScreen = pWin->drawable.pScreen;
97  winWindowPriv(pWin);
98  winScreenPriv(pScreen);
99
100#if CYGMULTIWINDOW_DEBUG
101  winTrace ("winCreateWindowMultiWindow - pWin: %p\n", pWin);
102#endif
103
104  WIN_UNWRAP(CreateWindow);
105  fResult = (*pScreen->CreateWindow) (pWin);
106  WIN_WRAP(CreateWindow, winCreateWindowMultiWindow);
107
108  /* Initialize some privates values */
109  pWinPriv->hRgn = NULL;
110  pWinPriv->hWnd = NULL;
111  pWinPriv->pScreenPriv = winGetScreenPriv(pWin->drawable.pScreen);
112  pWinPriv->fXKilled = FALSE;
113
114  return fResult;
115}
116
117
118/*
119 * DestroyWindow - See Porting Layer Definition - p. 37
120 */
121
122Bool
123winDestroyWindowMultiWindow (WindowPtr pWin)
124{
125  Bool			fResult = TRUE;
126  ScreenPtr		pScreen = pWin->drawable.pScreen;
127  winWindowPriv(pWin);
128  winScreenPriv(pScreen);
129
130#if CYGMULTIWINDOW_DEBUG
131  ErrorF ("winDestroyWindowMultiWindow - pWin: %p\n", pWin);
132#endif
133
134  WIN_UNWRAP(DestroyWindow);
135  fResult = (*pScreen->DestroyWindow)(pWin);
136  WIN_WRAP(DestroyWindow, winDestroyWindowMultiWindow);
137
138  /* Flag that the window has been destroyed */
139  pWinPriv->fXKilled = TRUE;
140
141  /* Kill the MS Windows window associated with this window */
142  winDestroyWindowsWindow (pWin);
143
144  return fResult;
145}
146
147
148/*
149 * PositionWindow - See Porting Layer Definition - p. 37
150 *
151 * This function adjusts the position and size of Windows window
152 * with respect to the underlying X window.  This is the inverse
153 * of winAdjustXWindow, which adjusts X window to Windows window.
154 */
155
156Bool
157winPositionWindowMultiWindow (WindowPtr pWin, int x, int y)
158{
159  Bool			fResult = TRUE;
160  int		        iX, iY, iWidth, iHeight;
161  ScreenPtr		pScreen = pWin->drawable.pScreen;
162  winWindowPriv(pWin);
163  winScreenPriv(pScreen);
164
165  HWND hWnd = pWinPriv->hWnd;
166  RECT rcNew;
167  RECT rcOld;
168#if CYGMULTIWINDOW_DEBUG
169  RECT rcClient;
170  RECT *lpRc;
171#endif
172  DWORD dwExStyle;
173  DWORD dwStyle;
174
175#if CYGMULTIWINDOW_DEBUG
176  winTrace ("winPositionWindowMultiWindow - pWin: %p\n", pWin);
177#endif
178
179  WIN_UNWRAP(PositionWindow);
180  fResult = (*pScreen->PositionWindow)(pWin, x, y);
181  WIN_WRAP(PositionWindow, winPositionWindowMultiWindow);
182
183#if CYGWINDOWING_DEBUG
184  ErrorF ("winPositionWindowMultiWindow: (x, y) = (%d, %d)\n",
185	  x, y);
186#endif
187
188  /* Bail out if the Windows window handle is bad */
189  if (!hWnd)
190    {
191#if CYGWINDOWING_DEBUG
192      ErrorF ("\timmediately return since hWnd is NULL\n");
193#endif
194      return fResult;
195    }
196
197  /* Get the Windows window style and extended style */
198  dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE);
199  dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE);
200
201  /* Get the X and Y location of the X window */
202  iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
203  iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
204
205  /* Get the height and width of the X window */
206  iWidth = pWin->drawable.width;
207  iHeight = pWin->drawable.height;
208
209  /* Store the origin, height, and width in a rectangle structure */
210  SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight);
211
212#if CYGMULTIWINDOW_DEBUG
213  lpRc = &rcNew;
214  ErrorF ("winPositionWindowMultiWindow - (%d ms)drawable (%d, %d)-(%d, %d)\n",
215	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
216#endif
217
218  /*
219   * Calculate the required size of the Windows window rectangle,
220   * given the size of the Windows window client area.
221   */
222  AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle);
223
224  /* Get a rectangle describing the old Windows window */
225  GetWindowRect (hWnd, &rcOld);
226
227#if CYGMULTIWINDOW_DEBUG
228  /* Get a rectangle describing the Windows window client area */
229  GetClientRect (hWnd, &rcClient);
230
231  lpRc = &rcNew;
232  ErrorF ("winPositionWindowMultiWindow - (%d ms)rcNew (%d, %d)-(%d, %d)\n",
233	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
234
235  lpRc = &rcOld;
236  ErrorF ("winPositionWindowMultiWindow - (%d ms)rcOld (%d, %d)-(%d, %d)\n",
237	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
238
239  lpRc = &rcClient;
240  ErrorF ("(%d ms)rcClient (%d, %d)-(%d, %d)\n",
241	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
242#endif
243
244  /* Check if the old rectangle and new rectangle are the same */
245  if (!EqualRect (&rcNew, &rcOld))
246    {
247#if CYGMULTIWINDOW_DEBUG
248      ErrorF ("winPositionWindowMultiWindow - Need to move\n");
249#endif
250
251#if CYGWINDOWING_DEBUG
252      ErrorF ("\tMoveWindow to (%ld, %ld) - %ldx%ld\n", rcNew.left, rcNew.top,
253	      rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
254#endif
255      /* Change the position and dimensions of the Windows window */
256      MoveWindow (hWnd,
257		  rcNew.left, rcNew.top,
258		  rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
259		  TRUE);
260    }
261  else
262    {
263#if CYGMULTIWINDOW_DEBUG
264      ErrorF ("winPositionWindowMultiWindow - Not need to move\n");
265#endif
266    }
267
268  return fResult;
269}
270
271
272/*
273 * ChangeWindowAttributes - See Porting Layer Definition - p. 37
274 */
275
276Bool
277winChangeWindowAttributesMultiWindow (WindowPtr pWin, unsigned long mask)
278{
279  Bool			fResult = TRUE;
280  ScreenPtr		pScreen = pWin->drawable.pScreen;
281  winScreenPriv(pScreen);
282
283#if CYGMULTIWINDOW_DEBUG
284  ErrorF ("winChangeWindowAttributesMultiWindow - pWin: %08x\n", pWin);
285#endif
286
287  WIN_UNWRAP(ChangeWindowAttributes);
288  fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
289  WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesMultiWindow);
290
291  /*
292   * NOTE: We do not currently need to do anything here.
293   */
294
295  return fResult;
296}
297
298
299/*
300 * UnmapWindow - See Porting Layer Definition - p. 37
301 * Also referred to as UnrealizeWindow
302 */
303
304Bool
305winUnmapWindowMultiWindow (WindowPtr pWin)
306{
307  Bool			fResult = TRUE;
308  ScreenPtr		pScreen = pWin->drawable.pScreen;
309  winWindowPriv(pWin);
310  winScreenPriv(pScreen);
311
312#if CYGMULTIWINDOW_DEBUG
313  ErrorF ("winUnmapWindowMultiWindow - pWin: %08x\n", pWin);
314#endif
315
316  WIN_UNWRAP(UnrealizeWindow);
317  fResult = (*pScreen->UnrealizeWindow)(pWin);
318  WIN_WRAP(UnrealizeWindow, winUnmapWindowMultiWindow);
319
320  /* Flag that the window has been killed */
321  pWinPriv->fXKilled = TRUE;
322
323  /* Destroy the Windows window associated with this X window */
324  winDestroyWindowsWindow (pWin);
325
326  return fResult;
327}
328
329
330/*
331 * MapWindow - See Porting Layer Definition - p. 37
332 * Also referred to as RealizeWindow
333 */
334
335Bool
336winMapWindowMultiWindow (WindowPtr pWin)
337{
338  Bool			fResult = TRUE;
339  ScreenPtr		pScreen = pWin->drawable.pScreen;
340  winWindowPriv(pWin);
341  winScreenPriv(pScreen);
342
343#if CYGMULTIWINDOW_DEBUG
344  ErrorF ("winMapWindowMultiWindow - pWin: %08x\n", pWin);
345#endif
346
347  WIN_UNWRAP(RealizeWindow);
348  fResult = (*pScreen->RealizeWindow)(pWin);
349  WIN_WRAP(RealizeWindow, winMapWindowMultiWindow);
350
351  /* Flag that this window has not been destroyed */
352  pWinPriv->fXKilled = FALSE;
353
354  /* Refresh/redisplay the Windows window associated with this X window */
355  winUpdateWindowsWindow (pWin);
356
357  /* Update the Windows window's shape */
358  winReshapeMultiWindow (pWin);
359  winUpdateRgnMultiWindow (pWin);
360
361  return fResult;
362}
363
364
365/*
366 * ReparentWindow - See Porting Layer Definition - p. 42
367 */
368
369void
370winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent)
371{
372  ScreenPtr		pScreen = pWin->drawable.pScreen;
373  winScreenPriv(pScreen);
374
375#if CYGMULTIWINDOW_DEBUG
376  ErrorF ("winReparentMultiWindow - pWin: %08x\n", pWin);
377#endif
378
379  WIN_UNWRAP(ReparentWindow);
380  if (pScreen->ReparentWindow)
381    (*pScreen->ReparentWindow)(pWin, pPriorParent);
382  WIN_WRAP(ReparentWindow, winReparentWindowMultiWindow);
383
384  /* Update the Windows window associated with this X window */
385  winUpdateWindowsWindow (pWin);
386}
387
388
389/*
390 * RestackWindow - Shuffle the z-order of a window
391 */
392
393void
394winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib)
395{
396#if 0
397  WindowPtr		pPrevWin;
398  UINT			uFlags;
399  HWND			hInsertAfter;
400  HWND                  hWnd = NULL;
401#endif
402  ScreenPtr		pScreen = pWin->drawable.pScreen;
403  winScreenPriv(pScreen);
404
405#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG
406  winTrace ("winRestackMultiWindow - %08x\n", pWin);
407#endif
408
409   WIN_UNWRAP(RestackWindow);
410   if (pScreen->RestackWindow)
411     (*pScreen->RestackWindow)(pWin, pOldNextSib);
412   WIN_WRAP(RestackWindow, winRestackWindowMultiWindow);
413
414#if 1
415  /*
416   * Calling winReorderWindowsMultiWindow here means our window manager
417   * (i.e. Windows Explorer) has initiative to determine Z order.
418   */
419  if (pWin->nextSib != pOldNextSib)
420    winReorderWindowsMultiWindow ();
421#else
422  /* Bail out if no window privates or window handle is invalid */
423  if (!pWinPriv || !pWinPriv->hWnd)
424    return;
425
426  /* Get a pointer to our previous sibling window */
427  pPrevWin = pWin->prevSib;
428
429  /*
430   * Look for a sibling window with
431   * valid privates and window handle
432   */
433  while (pPrevWin
434	 && !winGetWindowPriv(pPrevWin)
435	 && !winGetWindowPriv(pPrevWin)->hWnd)
436    pPrevWin = pPrevWin->prevSib;
437
438  /* Check if we found a valid sibling */
439  if (pPrevWin)
440    {
441      /* Valid sibling - get handle to insert window after */
442      hInsertAfter = winGetWindowPriv(pPrevWin)->hWnd;
443      uFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
444
445      hWnd = GetNextWindow (pWinPriv->hWnd, GW_HWNDPREV);
446
447      do
448	{
449	  if (GetProp (hWnd, WIN_WINDOW_PROP))
450	    {
451	      if (hWnd == winGetWindowPriv(pPrevWin)->hWnd)
452		{
453		  uFlags |= SWP_NOZORDER;
454		}
455	      break;
456	    }
457	  hWnd = GetNextWindow (hWnd, GW_HWNDPREV);
458	}
459      while (hWnd);
460    }
461  else
462    {
463      /* No valid sibling - make this window the top window */
464      hInsertAfter = HWND_TOP;
465      uFlags = SWP_NOMOVE | SWP_NOSIZE;
466    }
467
468  /* Perform the restacking operation in Windows */
469  SetWindowPos (pWinPriv->hWnd,
470		hInsertAfter,
471		0, 0,
472		0, 0,
473		uFlags);
474#endif
475}
476
477
478/*
479 * winCreateWindowsWindow - Create a Windows window associated with an X window
480 */
481
482void
483winCreateWindowsWindow (WindowPtr pWin)
484{
485  int                   iX, iY;
486  int			iWidth;
487  int			iHeight;
488  HWND			hWnd;
489  HWND			hFore = NULL;
490  winWindowPriv(pWin);
491  HICON			hIcon;
492  HICON			hIconSmall;
493  winPrivScreenPtr	pScreenPriv = pWinPriv->pScreenPriv;
494  WinXSizeHints         hints;
495  WindowPtr		pDaddy;
496
497  winInitMultiWindowClass();
498
499#if CYGMULTIWINDOW_DEBUG
500  ErrorF ("winCreateWindowsWindow - pWin: %08x\n", pWin);
501#endif
502
503  iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
504  iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
505
506  iWidth = pWin->drawable.width;
507  iHeight = pWin->drawable.height;
508
509  /* ensure window actually ends up somewhere visible */
510  if (iX > GetSystemMetrics (SM_CXVIRTUALSCREEN))
511    iX = CW_USEDEFAULT;
512
513  if (iY > GetSystemMetrics (SM_CYVIRTUALSCREEN))
514    iY = CW_USEDEFAULT;
515
516  if (winMultiWindowGetTransientFor (pWin, &pDaddy))
517    {
518      if (pDaddy)
519      {
520        hFore = GetForegroundWindow();
521        if (hFore && (pDaddy != (WindowPtr)GetProp(hFore, WIN_WID_PROP))) hFore = NULL;
522      }
523    }
524  else
525    {
526      /* Default positions if none specified */
527      if (!winMultiWindowGetWMNormalHints(pWin, &hints))
528        hints.flags = 0;
529      if (!(hints.flags & (USPosition|PPosition)) &&
530          !pWin->overrideRedirect)
531      {
532        iX = CW_USEDEFAULT;
533        iY = CW_USEDEFAULT;
534      }
535    }
536
537  /* Create the window */
538  /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */
539  /* CW_USEDEFAULT, change back to popup after creation */
540  hWnd = CreateWindowExA (WS_EX_TOOLWINDOW,	/* Extended styles */
541			  WINDOW_CLASS_X,	/* Class name */
542			  WINDOW_TITLE_X,	/* Window name */
543			  WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
544			  iX,			/* Horizontal position */
545			  iY,			/* Vertical position */
546			  iWidth,		/* Right edge */
547			  iHeight,		/* Bottom edge */
548			  hFore,		/* Null or Parent window if transient*/
549			  (HMENU) NULL,		/* No menu */
550			  GetModuleHandle (NULL), /* Instance handle */
551			  pWin);		/* ScreenPrivates */
552  if (hWnd == NULL)
553    {
554      ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n",
555	      (int) GetLastError ());
556    }
557  pWinPriv->hWnd = hWnd;
558
559  /* Set application or .XWinrc defined Icons */
560  winSelectIcons(pWin, &hIcon, &hIconSmall);
561  if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
562  if (hIconSmall) SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
563
564  /* Change style back to popup, already placed... */
565  SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
566  SetWindowPos (hWnd, 0, 0, 0, 0, 0,
567		SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
568  /* Make sure it gets the proper system menu for a WS_POPUP, too */
569  GetSystemMenu (hWnd, TRUE);
570
571  /* Cause any .XWinrc menus to be added in main WNDPROC */
572  PostMessage (hWnd, WM_INIT_SYS_MENU, 0, 0);
573
574  SetProp (hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin));
575
576  /* Flag that this Windows window handles its own activation */
577  SetProp (hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0);
578
579  /* Call engine-specific create window procedure */
580  (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin);
581}
582
583
584Bool winInDestroyWindowsWindow = FALSE;
585/*
586 * winDestroyWindowsWindow - Destroy a Windows window associated
587 * with an X window
588 */
589static void
590winDestroyWindowsWindow (WindowPtr pWin)
591{
592  MSG			msg;
593  winWindowPriv(pWin);
594  BOOL			oldstate = winInDestroyWindowsWindow;
595
596#if CYGMULTIWINDOW_DEBUG
597  ErrorF ("winDestroyWindowsWindow\n");
598#endif
599
600  /* Bail out if the Windows window handle is invalid */
601  if (pWinPriv->hWnd == NULL)
602    return;
603
604  winInDestroyWindowsWindow = TRUE;
605
606  SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, NULL);
607  /* Destroy the Windows window */
608  DestroyWindow (pWinPriv->hWnd);
609
610  /* Null our handle to the Window so referencing it will cause an error */
611  pWinPriv->hWnd = NULL;
612
613  /* Process all messages on our queue */
614  while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
615    {
616      if (g_hDlgDepthChange == 0 || !IsDialogMessage (g_hDlgDepthChange, &msg))
617	{
618	  DispatchMessage (&msg);
619	}
620    }
621
622  winInDestroyWindowsWindow = oldstate;
623
624#if CYGMULTIWINDOW_DEBUG
625  ErrorF ("-winDestroyWindowsWindow\n");
626#endif
627}
628
629
630/*
631 * winUpdateWindowsWindow - Redisplay/redraw a Windows window
632 * associated with an X window
633 */
634
635static void
636winUpdateWindowsWindow (WindowPtr pWin)
637{
638  winWindowPriv(pWin);
639  HWND			hWnd = pWinPriv->hWnd;
640
641#if CYGMULTIWINDOW_DEBUG
642  ErrorF ("winUpdateWindowsWindow\n");
643#endif
644
645  /* Check if the Windows window's parents have been destroyed */
646  if (pWin->parent != NULL
647      && pWin->parent->parent == NULL
648      && pWin->mapped)
649    {
650      /* Create the Windows window if it has been destroyed */
651      if (hWnd == NULL)
652	{
653	  winCreateWindowsWindow (pWin);
654	  assert (pWinPriv->hWnd != NULL);
655	}
656
657      /* Display the window without activating it */
658      ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE);
659
660      /* Send first paint message */
661      UpdateWindow (pWinPriv->hWnd);
662    }
663  else if (hWnd != NULL)
664    {
665      /* Destroy the Windows window if its parents are destroyed */
666      winDestroyWindowsWindow (pWin);
667      assert (pWinPriv->hWnd == NULL);
668    }
669
670#if CYGMULTIWINDOW_DEBUG
671  ErrorF ("-winUpdateWindowsWindow\n");
672#endif
673}
674
675
676/*
677 * winGetWindowID -
678 */
679
680XID
681winGetWindowID (WindowPtr pWin)
682{
683  WindowIDPairRec	wi = {pWin, 0};
684  ClientPtr		c = wClient(pWin);
685
686  /* */
687  FindClientResourcesByType (c, RT_WINDOW, winFindWindow, &wi);
688
689#if CYGMULTIWINDOW_DEBUG
690  ErrorF ("winGetWindowID - Window ID: %d\n", wi.id);
691#endif
692
693  return wi.id;
694}
695
696
697/*
698 * winFindWindow -
699 */
700
701static void
702winFindWindow (pointer value, XID id, pointer cdata)
703{
704  WindowIDPairPtr	wi = (WindowIDPairPtr)cdata;
705
706  if (value == wi->value)
707    {
708      wi->id = id;
709    }
710}
711
712
713/*
714 * winReorderWindowsMultiWindow -
715 */
716
717void
718winReorderWindowsMultiWindow (void)
719{
720  HWND hwnd = NULL;
721  WindowPtr pWin = NULL;
722  WindowPtr pWinSib = NULL;
723  XID vlist[2];
724  static Bool fRestacking = FALSE; /* Avoid recusive calls to this function */
725  DWORD dwCurrentProcessID = GetCurrentProcessId ();
726  DWORD dwWindowProcessID = 0;
727
728#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG
729  winTrace ("winReorderWindowsMultiWindow\n");
730#endif
731
732  if (fRestacking)
733    {
734      /* It is a recusive call so immediately exit */
735#if CYGWINDOWING_DEBUG
736      ErrorF ("winReorderWindowsMultiWindow - "
737	      "exit because fRestacking == TRUE\n");
738#endif
739      return;
740    }
741  fRestacking = TRUE;
742
743  /* Loop through top level Window windows, descending in Z order */
744  for ( hwnd = GetTopWindow (NULL);
745	hwnd;
746	hwnd = GetNextWindow (hwnd, GW_HWNDNEXT) )
747    {
748      /* Don't take care of other Cygwin/X process's windows */
749      GetWindowThreadProcessId (hwnd, &dwWindowProcessID);
750
751      if ( GetProp (hwnd, WIN_WINDOW_PROP)
752	   && (dwWindowProcessID == dwCurrentProcessID)
753	   && !IsIconic (hwnd) ) /* ignore minimized windows */
754	{
755	  pWinSib = pWin;
756	  pWin = GetProp (hwnd, WIN_WINDOW_PROP);
757
758	  if (!pWinSib)
759	    { /* 1st window - raise to the top */
760	      vlist[0] = Above;
761
762	      ConfigureWindow (pWin, CWStackMode, vlist, wClient(pWin));
763	    }
764	  else
765	    { /* 2nd or deeper windows - just below the previous one */
766	      vlist[0] = winGetWindowID (pWinSib);
767	      vlist[1] = Below;
768
769	      ConfigureWindow (pWin, CWSibling | CWStackMode,
770			       vlist, wClient(pWin));
771	    }
772	}
773    }
774
775  fRestacking = FALSE;
776}
777
778
779/*
780 * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE
781 */
782
783void
784winMinimizeWindow (Window id)
785{
786  WindowPtr		pWin;
787  winPrivWinPtr	pWinPriv;
788#ifdef XWIN_MULTIWINDOWEXTWM
789  win32RootlessWindowPtr pRLWinPriv;
790#endif
791  HWND hWnd;
792  ScreenPtr pScreen = NULL;
793  winPrivScreenPtr pScreenPriv = NULL;
794  winScreenInfo *pScreenInfo = NULL;
795
796#if CYGWINDOWING_DEBUG
797  ErrorF ("winMinimizeWindow\n");
798#endif
799
800  dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, DixUnknownAccess);
801  if (!pWin)
802  {
803      ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__);
804      return;
805  }
806
807  pScreen = pWin->drawable.pScreen;
808  if (pScreen) pScreenPriv = winGetScreenPriv(pScreen);
809  if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
810
811#ifdef XWIN_MULTIWINDOWEXTWM
812  if (pScreenPriv && pScreenInfo->fInternalWM)
813    {
814      pRLWinPriv  = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
815      hWnd = pRLWinPriv->hWnd;
816    }
817  else
818#else
819  if (pScreenPriv)
820#endif
821    {
822      pWinPriv = winGetWindowPriv (pWin);
823      hWnd = pWinPriv->hWnd;
824    }
825
826  ShowWindow (hWnd, SW_MINIMIZE);
827}
828
829
830/*
831 * CopyWindow - See Porting Layer Definition - p. 39
832 */
833void
834winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt,
835			  RegionPtr oldRegion)
836{
837  ScreenPtr		pScreen = pWin->drawable.pScreen;
838  winScreenPriv(pScreen);
839
840#if CYGWINDOWING_DEBUG
841  ErrorF ("CopyWindowMultiWindow\n");
842#endif
843  WIN_UNWRAP(CopyWindow);
844  (*pScreen->CopyWindow)(pWin, oldpt, oldRegion);
845  WIN_WRAP(CopyWindow, winCopyWindowMultiWindow);
846}
847
848
849/*
850 * MoveWindow - See Porting Layer Definition - p. 42
851 */
852void
853winMoveWindowMultiWindow (WindowPtr pWin, int x, int y,
854			  WindowPtr pSib, VTKind kind)
855{
856  ScreenPtr		pScreen = pWin->drawable.pScreen;
857  winScreenPriv(pScreen);
858
859#if CYGWINDOWING_DEBUG
860  ErrorF ("MoveWindowMultiWindow to (%d, %d)\n", x, y);
861#endif
862
863  WIN_UNWRAP(MoveWindow);
864  (*pScreen->MoveWindow)(pWin, x, y, pSib, kind);
865  WIN_WRAP(MoveWindow, winMoveWindowMultiWindow);
866}
867
868
869/*
870 * ResizeWindow - See Porting Layer Definition - p. 42
871 */
872void
873winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w,
874			    unsigned int h, WindowPtr pSib)
875{
876  ScreenPtr		pScreen = pWin->drawable.pScreen;
877  winScreenPriv(pScreen);
878
879#if CYGWINDOWING_DEBUG
880  ErrorF ("ResizeWindowMultiWindow to (%d, %d) - %dx%d\n", x, y, w, h);
881#endif
882  WIN_UNWRAP(ResizeWindow);
883  (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
884  WIN_WRAP(ResizeWindow, winResizeWindowMultiWindow);
885}
886
887
888/*
889 * winAdjustXWindow
890 *
891 * Move and resize X window with respect to corresponding Windows window.
892 * This is called from WM_MOVE/WM_SIZE handlers when the user performs
893 * any windowing operation (move, resize, minimize, maximize, restore).
894 *
895 * The functionality is the inverse of winPositionWindowMultiWindow, which
896 * adjusts Windows window with respect to X window.
897 */
898int
899winAdjustXWindow (WindowPtr pWin, HWND hwnd)
900{
901  RECT rcDraw; /* Rect made from pWin->drawable to be adjusted */
902  RECT rcWin;  /* The source: WindowRect from hwnd */
903  DrawablePtr pDraw;
904  XID vlist[4];
905  LONG dX, dY, dW, dH, x, y;
906  DWORD dwStyle, dwExStyle;
907
908#define WIDTH(rc) (rc.right - rc.left)
909#define HEIGHT(rc) (rc.bottom - rc.top)
910
911#if CYGWINDOWING_DEBUG
912  ErrorF ("winAdjustXWindow\n");
913#endif
914
915  if (IsIconic (hwnd))
916    {
917#if CYGWINDOWING_DEBUG
918      ErrorF ("\timmediately return because the window is iconized\n");
919#endif
920      /*
921       * If the Windows window is minimized, its WindowRect has
922       * meaningless values so we don't adjust X window to it.
923       */
924      vlist[0] = 0;
925      vlist[1] = 0;
926      return ConfigureWindow (pWin, CWX | CWY, vlist, wClient(pWin));
927    }
928
929  pDraw = &pWin->drawable;
930
931  /* Calculate the window rect from the drawable */
932  x = pDraw->x + GetSystemMetrics (SM_XVIRTUALSCREEN);
933  y = pDraw->y + GetSystemMetrics (SM_YVIRTUALSCREEN);
934  SetRect (&rcDraw, x, y, x + pDraw->width, y + pDraw->height);
935#ifdef CYGMULTIWINDOW_DEBUG
936          winDebug("\tDrawable extend {%d, %d, %d, %d}, {%d, %d}\n",
937              rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom,
938              rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top);
939#endif
940  dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE);
941  dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE);
942#ifdef CYGMULTIWINDOW_DEBUG
943          winDebug("\tWindowStyle: %08x %08x\n", dwStyle, dwExStyle);
944#endif
945  AdjustWindowRectEx (&rcDraw, dwStyle, FALSE, dwExStyle);
946
947  /* The source of adjust */
948  GetWindowRect (hwnd, &rcWin);
949#ifdef CYGMULTIWINDOW_DEBUG
950          winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n",
951              rcWin.left, rcWin.top, rcWin.right, rcWin.bottom,
952              rcWin.right - rcWin.left, rcWin.bottom - rcWin.top);
953          winDebug("\tDraw extend {%d, %d, %d, %d}, {%d, %d}\n",
954              rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom,
955              rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top);
956#endif
957
958  if (EqualRect (&rcDraw, &rcWin)) {
959    /* Bail if no adjust is needed */
960#if CYGWINDOWING_DEBUG
961    ErrorF ("\treturn because already adjusted\n");
962#endif
963    return 0;
964  }
965
966  /* Calculate delta values */
967  dX = rcWin.left - rcDraw.left;
968  dY = rcWin.top - rcDraw.top;
969  dW = WIDTH(rcWin) - WIDTH(rcDraw);
970  dH = HEIGHT(rcWin) - HEIGHT(rcDraw);
971
972  /*
973   * Adjust.
974   * We may only need to move (vlist[0] and [1]), or only resize
975   * ([2] and [3]) but currently we set all the parameters and leave
976   * the decision to ConfigureWindow.  The reason is code simplicity.
977  */
978  vlist[0] = pDraw->x + dX - wBorderWidth(pWin);
979  vlist[1] = pDraw->y + dY - wBorderWidth(pWin);
980  vlist[2] = pDraw->width + dW;
981  vlist[3] = pDraw->height + dH;
982#if CYGWINDOWING_DEBUG
983  ErrorF ("\tConfigureWindow to (%ld, %ld) - %ldx%ld\n", vlist[0], vlist[1],
984	  vlist[2], vlist[3]);
985#endif
986  return ConfigureWindow (pWin, CWX | CWY | CWWidth | CWHeight,
987			  vlist, wClient(pWin));
988
989#undef WIDTH
990#undef HEIGHT
991}
992
993