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