1706f2543Smrg/*
2706f2543Smrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3706f2543Smrg *Copyright (C) Colin Harrison 2005-2008
4706f2543Smrg *
5706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining
6706f2543Smrg * a copy of this software and associated documentation files (the
7706f2543Smrg *"Software"), to deal in the Software without restriction, including
8706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish,
9706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to
10706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to
11706f2543Smrg *the following conditions:
12706f2543Smrg *
13706f2543Smrg *The above copyright notice and this permission notice shall be
14706f2543Smrg *included in all copies or substantial portions of the Software.
15706f2543Smrg *
16706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23706f2543Smrg *
24706f2543Smrg *Except as contained in this notice, the name of the XFree86 Project
25706f2543Smrg *shall not be used in advertising or otherwise to promote the sale, use
26706f2543Smrg *or other dealings in this Software without prior written authorization
27706f2543Smrg *from the XFree86 Project.
28706f2543Smrg *
29706f2543Smrg * Authors:	Kensuke Matsuzaki
30706f2543Smrg *		Earle F. Philhower, III
31706f2543Smrg *		Harold L Hunt II
32706f2543Smrg *              Colin Harrison
33706f2543Smrg */
34706f2543Smrg
35706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
36706f2543Smrg#include <xwin-config.h>
37706f2543Smrg#endif
38706f2543Smrg#include "win.h"
39706f2543Smrg#include "dixevents.h"
40706f2543Smrg#include "winmultiwindowclass.h"
41706f2543Smrg
42706f2543Smrg/*
43706f2543Smrg * Prototypes for local functions
44706f2543Smrg */
45706f2543Smrg
46706f2543Smrgvoid
47706f2543SmrgwinCreateWindowsWindow (WindowPtr pWin);
48706f2543Smrg
49706f2543Smrgstatic void
50706f2543SmrgwinDestroyWindowsWindow (WindowPtr pWin);
51706f2543Smrg
52706f2543Smrgstatic void
53706f2543SmrgwinUpdateWindowsWindow (WindowPtr pWin);
54706f2543Smrg
55706f2543Smrgstatic void
56706f2543SmrgwinFindWindow (pointer value, XID id, pointer cdata);
57706f2543Smrg
58706f2543Smrgstatic
59706f2543Smrgvoid winInitMultiWindowClass(void)
60706f2543Smrg{
61706f2543Smrg  static wATOM atomXWinClass=0;
62706f2543Smrg  WNDCLASSEX wcx;
63706f2543Smrg
64706f2543Smrg  if (atomXWinClass==0)
65706f2543Smrg  {
66706f2543Smrg    /* Setup our window class */
67706f2543Smrg    wcx.cbSize=sizeof(WNDCLASSEX);
68706f2543Smrg    wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0);
69706f2543Smrg    wcx.lpfnWndProc = winTopLevelWindowProc;
70706f2543Smrg    wcx.cbClsExtra = 0;
71706f2543Smrg    wcx.cbWndExtra = 0;
72706f2543Smrg    wcx.hInstance = g_hInstance;
73706f2543Smrg    wcx.hIcon = g_hIconX;
74706f2543Smrg    wcx.hCursor = 0;
75706f2543Smrg    wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
76706f2543Smrg    wcx.lpszMenuName = NULL;
77706f2543Smrg    wcx.lpszClassName = WINDOW_CLASS_X;
78706f2543Smrg    wcx.hIconSm = g_hSmallIconX;
79706f2543Smrg
80706f2543Smrg#if CYGMULTIWINDOW_DEBUG
81706f2543Smrg    ErrorF ("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X);
82706f2543Smrg#endif
83706f2543Smrg
84706f2543Smrg    atomXWinClass = RegisterClassEx (&wcx);
85706f2543Smrg  }
86706f2543Smrg}
87706f2543Smrg
88706f2543Smrg/*
89706f2543Smrg * CreateWindow - See Porting Layer Definition - p. 37
90706f2543Smrg */
91706f2543Smrg
92706f2543SmrgBool
93706f2543SmrgwinCreateWindowMultiWindow (WindowPtr pWin)
94706f2543Smrg{
95706f2543Smrg  Bool			fResult = TRUE;
96706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
97706f2543Smrg  winWindowPriv(pWin);
98706f2543Smrg  winScreenPriv(pScreen);
99706f2543Smrg
100706f2543Smrg#if CYGMULTIWINDOW_DEBUG
101706f2543Smrg  winTrace ("winCreateWindowMultiWindow - pWin: %p\n", pWin);
102706f2543Smrg#endif
103706f2543Smrg
104706f2543Smrg  WIN_UNWRAP(CreateWindow);
105706f2543Smrg  fResult = (*pScreen->CreateWindow) (pWin);
106706f2543Smrg  WIN_WRAP(CreateWindow, winCreateWindowMultiWindow);
107706f2543Smrg
108706f2543Smrg  /* Initialize some privates values */
109706f2543Smrg  pWinPriv->hRgn = NULL;
110706f2543Smrg  pWinPriv->hWnd = NULL;
111706f2543Smrg  pWinPriv->pScreenPriv = winGetScreenPriv(pWin->drawable.pScreen);
112706f2543Smrg  pWinPriv->fXKilled = FALSE;
113706f2543Smrg
114706f2543Smrg  return fResult;
115706f2543Smrg}
116706f2543Smrg
117706f2543Smrg
118706f2543Smrg/*
119706f2543Smrg * DestroyWindow - See Porting Layer Definition - p. 37
120706f2543Smrg */
121706f2543Smrg
122706f2543SmrgBool
123706f2543SmrgwinDestroyWindowMultiWindow (WindowPtr pWin)
124706f2543Smrg{
125706f2543Smrg  Bool			fResult = TRUE;
126706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
127706f2543Smrg  winWindowPriv(pWin);
128706f2543Smrg  winScreenPriv(pScreen);
129706f2543Smrg
130706f2543Smrg#if CYGMULTIWINDOW_DEBUG
131706f2543Smrg  ErrorF ("winDestroyWindowMultiWindow - pWin: %p\n", pWin);
132706f2543Smrg#endif
133706f2543Smrg
134706f2543Smrg  WIN_UNWRAP(DestroyWindow);
135706f2543Smrg  fResult = (*pScreen->DestroyWindow)(pWin);
136706f2543Smrg  WIN_WRAP(DestroyWindow, winDestroyWindowMultiWindow);
137706f2543Smrg
138706f2543Smrg  /* Flag that the window has been destroyed */
139706f2543Smrg  pWinPriv->fXKilled = TRUE;
140706f2543Smrg
141706f2543Smrg  /* Kill the MS Windows window associated with this window */
142706f2543Smrg  winDestroyWindowsWindow (pWin);
143706f2543Smrg
144706f2543Smrg  return fResult;
145706f2543Smrg}
146706f2543Smrg
147706f2543Smrg
148706f2543Smrg/*
149706f2543Smrg * PositionWindow - See Porting Layer Definition - p. 37
150706f2543Smrg *
151706f2543Smrg * This function adjusts the position and size of Windows window
152706f2543Smrg * with respect to the underlying X window.  This is the inverse
153706f2543Smrg * of winAdjustXWindow, which adjusts X window to Windows window.
154706f2543Smrg */
155706f2543Smrg
156706f2543SmrgBool
157706f2543SmrgwinPositionWindowMultiWindow (WindowPtr pWin, int x, int y)
158706f2543Smrg{
159706f2543Smrg  Bool			fResult = TRUE;
160706f2543Smrg  int		        iX, iY, iWidth, iHeight;
161706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
162706f2543Smrg  winWindowPriv(pWin);
163706f2543Smrg  winScreenPriv(pScreen);
164706f2543Smrg
165706f2543Smrg  HWND hWnd = pWinPriv->hWnd;
166706f2543Smrg  RECT rcNew;
167706f2543Smrg  RECT rcOld;
168706f2543Smrg#if CYGMULTIWINDOW_DEBUG
169706f2543Smrg  RECT rcClient;
170706f2543Smrg  RECT *lpRc;
171706f2543Smrg#endif
172706f2543Smrg  DWORD dwExStyle;
173706f2543Smrg  DWORD dwStyle;
174706f2543Smrg
175706f2543Smrg#if CYGMULTIWINDOW_DEBUG
176706f2543Smrg  winTrace ("winPositionWindowMultiWindow - pWin: %p\n", pWin);
177706f2543Smrg#endif
178706f2543Smrg
179706f2543Smrg  WIN_UNWRAP(PositionWindow);
180706f2543Smrg  fResult = (*pScreen->PositionWindow)(pWin, x, y);
181706f2543Smrg  WIN_WRAP(PositionWindow, winPositionWindowMultiWindow);
182706f2543Smrg
183706f2543Smrg#if CYGWINDOWING_DEBUG
184706f2543Smrg  ErrorF ("winPositionWindowMultiWindow: (x, y) = (%d, %d)\n",
185706f2543Smrg	  x, y);
186706f2543Smrg#endif
187706f2543Smrg
188706f2543Smrg  /* Bail out if the Windows window handle is bad */
189706f2543Smrg  if (!hWnd)
190706f2543Smrg    {
191706f2543Smrg#if CYGWINDOWING_DEBUG
192706f2543Smrg      ErrorF ("\timmediately return since hWnd is NULL\n");
193706f2543Smrg#endif
194706f2543Smrg      return fResult;
195706f2543Smrg    }
196706f2543Smrg
197706f2543Smrg  /* Get the Windows window style and extended style */
198706f2543Smrg  dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE);
199706f2543Smrg  dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE);
200706f2543Smrg
201706f2543Smrg  /* Get the X and Y location of the X window */
202706f2543Smrg  iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
203706f2543Smrg  iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
204706f2543Smrg
205706f2543Smrg  /* Get the height and width of the X window */
206706f2543Smrg  iWidth = pWin->drawable.width;
207706f2543Smrg  iHeight = pWin->drawable.height;
208706f2543Smrg
209706f2543Smrg  /* Store the origin, height, and width in a rectangle structure */
210706f2543Smrg  SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight);
211706f2543Smrg
212706f2543Smrg#if CYGMULTIWINDOW_DEBUG
213706f2543Smrg  lpRc = &rcNew;
214706f2543Smrg  ErrorF ("winPositionWindowMultiWindow - (%d ms)drawable (%d, %d)-(%d, %d)\n",
215706f2543Smrg	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
216706f2543Smrg#endif
217706f2543Smrg
218706f2543Smrg  /*
219706f2543Smrg   * Calculate the required size of the Windows window rectangle,
220706f2543Smrg   * given the size of the Windows window client area.
221706f2543Smrg   */
222706f2543Smrg  AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle);
223706f2543Smrg
224706f2543Smrg  /* Get a rectangle describing the old Windows window */
225706f2543Smrg  GetWindowRect (hWnd, &rcOld);
226706f2543Smrg
227706f2543Smrg#if CYGMULTIWINDOW_DEBUG
228706f2543Smrg  /* Get a rectangle describing the Windows window client area */
229706f2543Smrg  GetClientRect (hWnd, &rcClient);
230706f2543Smrg
231706f2543Smrg  lpRc = &rcNew;
232706f2543Smrg  ErrorF ("winPositionWindowMultiWindow - (%d ms)rcNew (%d, %d)-(%d, %d)\n",
233706f2543Smrg	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
234706f2543Smrg
235706f2543Smrg  lpRc = &rcOld;
236706f2543Smrg  ErrorF ("winPositionWindowMultiWindow - (%d ms)rcOld (%d, %d)-(%d, %d)\n",
237706f2543Smrg	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
238706f2543Smrg
239706f2543Smrg  lpRc = &rcClient;
240706f2543Smrg  ErrorF ("(%d ms)rcClient (%d, %d)-(%d, %d)\n",
241706f2543Smrg	  GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
242706f2543Smrg#endif
243706f2543Smrg
244706f2543Smrg  /* Check if the old rectangle and new rectangle are the same */
245706f2543Smrg  if (!EqualRect (&rcNew, &rcOld))
246706f2543Smrg    {
247706f2543Smrg#if CYGMULTIWINDOW_DEBUG
248706f2543Smrg      ErrorF ("winPositionWindowMultiWindow - Need to move\n");
249706f2543Smrg#endif
250706f2543Smrg
251706f2543Smrg#if CYGWINDOWING_DEBUG
252706f2543Smrg      ErrorF ("\tMoveWindow to (%ld, %ld) - %ldx%ld\n", rcNew.left, rcNew.top,
253706f2543Smrg	      rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
254706f2543Smrg#endif
255706f2543Smrg      /* Change the position and dimensions of the Windows window */
256706f2543Smrg      MoveWindow (hWnd,
257706f2543Smrg		  rcNew.left, rcNew.top,
258706f2543Smrg		  rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
259706f2543Smrg		  TRUE);
260706f2543Smrg    }
261706f2543Smrg  else
262706f2543Smrg    {
263706f2543Smrg#if CYGMULTIWINDOW_DEBUG
264706f2543Smrg      ErrorF ("winPositionWindowMultiWindow - Not need to move\n");
265706f2543Smrg#endif
266706f2543Smrg    }
267706f2543Smrg
268706f2543Smrg  return fResult;
269706f2543Smrg}
270706f2543Smrg
271706f2543Smrg
272706f2543Smrg/*
273706f2543Smrg * ChangeWindowAttributes - See Porting Layer Definition - p. 37
274706f2543Smrg */
275706f2543Smrg
276706f2543SmrgBool
277706f2543SmrgwinChangeWindowAttributesMultiWindow (WindowPtr pWin, unsigned long mask)
278706f2543Smrg{
279706f2543Smrg  Bool			fResult = TRUE;
280706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
281706f2543Smrg  winScreenPriv(pScreen);
282706f2543Smrg
283706f2543Smrg#if CYGMULTIWINDOW_DEBUG
284706f2543Smrg  ErrorF ("winChangeWindowAttributesMultiWindow - pWin: %08x\n", pWin);
285706f2543Smrg#endif
286706f2543Smrg
287706f2543Smrg  WIN_UNWRAP(ChangeWindowAttributes);
288706f2543Smrg  fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
289706f2543Smrg  WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesMultiWindow);
290706f2543Smrg
291706f2543Smrg  /*
292706f2543Smrg   * NOTE: We do not currently need to do anything here.
293706f2543Smrg   */
294706f2543Smrg
295706f2543Smrg  return fResult;
296706f2543Smrg}
297706f2543Smrg
298706f2543Smrg
299706f2543Smrg/*
300706f2543Smrg * UnmapWindow - See Porting Layer Definition - p. 37
301706f2543Smrg * Also referred to as UnrealizeWindow
302706f2543Smrg */
303706f2543Smrg
304706f2543SmrgBool
305706f2543SmrgwinUnmapWindowMultiWindow (WindowPtr pWin)
306706f2543Smrg{
307706f2543Smrg  Bool			fResult = TRUE;
308706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
309706f2543Smrg  winWindowPriv(pWin);
310706f2543Smrg  winScreenPriv(pScreen);
311706f2543Smrg
312706f2543Smrg#if CYGMULTIWINDOW_DEBUG
313706f2543Smrg  ErrorF ("winUnmapWindowMultiWindow - pWin: %08x\n", pWin);
314706f2543Smrg#endif
315706f2543Smrg
316706f2543Smrg  WIN_UNWRAP(UnrealizeWindow);
317706f2543Smrg  fResult = (*pScreen->UnrealizeWindow)(pWin);
318706f2543Smrg  WIN_WRAP(UnrealizeWindow, winUnmapWindowMultiWindow);
319706f2543Smrg
320706f2543Smrg  /* Flag that the window has been killed */
321706f2543Smrg  pWinPriv->fXKilled = TRUE;
322706f2543Smrg
323706f2543Smrg  /* Destroy the Windows window associated with this X window */
324706f2543Smrg  winDestroyWindowsWindow (pWin);
325706f2543Smrg
326706f2543Smrg  return fResult;
327706f2543Smrg}
328706f2543Smrg
329706f2543Smrg
330706f2543Smrg/*
331706f2543Smrg * MapWindow - See Porting Layer Definition - p. 37
332706f2543Smrg * Also referred to as RealizeWindow
333706f2543Smrg */
334706f2543Smrg
335706f2543SmrgBool
336706f2543SmrgwinMapWindowMultiWindow (WindowPtr pWin)
337706f2543Smrg{
338706f2543Smrg  Bool			fResult = TRUE;
339706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
340706f2543Smrg  winWindowPriv(pWin);
341706f2543Smrg  winScreenPriv(pScreen);
342706f2543Smrg
343706f2543Smrg#if CYGMULTIWINDOW_DEBUG
344706f2543Smrg  ErrorF ("winMapWindowMultiWindow - pWin: %08x\n", pWin);
345706f2543Smrg#endif
346706f2543Smrg
347706f2543Smrg  WIN_UNWRAP(RealizeWindow);
348706f2543Smrg  fResult = (*pScreen->RealizeWindow)(pWin);
349706f2543Smrg  WIN_WRAP(RealizeWindow, winMapWindowMultiWindow);
350706f2543Smrg
351706f2543Smrg  /* Flag that this window has not been destroyed */
352706f2543Smrg  pWinPriv->fXKilled = FALSE;
353706f2543Smrg
354706f2543Smrg  /* Refresh/redisplay the Windows window associated with this X window */
355706f2543Smrg  winUpdateWindowsWindow (pWin);
356706f2543Smrg
357706f2543Smrg  /* Update the Windows window's shape */
358706f2543Smrg  winReshapeMultiWindow (pWin);
359706f2543Smrg  winUpdateRgnMultiWindow (pWin);
360706f2543Smrg
361706f2543Smrg  return fResult;
362706f2543Smrg}
363706f2543Smrg
364706f2543Smrg
365706f2543Smrg/*
366706f2543Smrg * ReparentWindow - See Porting Layer Definition - p. 42
367706f2543Smrg */
368706f2543Smrg
369706f2543Smrgvoid
370706f2543SmrgwinReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent)
371706f2543Smrg{
372706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
373706f2543Smrg  winScreenPriv(pScreen);
374706f2543Smrg
375706f2543Smrg#if CYGMULTIWINDOW_DEBUG
376706f2543Smrg  ErrorF ("winReparentMultiWindow - pWin: %08x\n", pWin);
377706f2543Smrg#endif
378706f2543Smrg
379706f2543Smrg  WIN_UNWRAP(ReparentWindow);
380706f2543Smrg  if (pScreen->ReparentWindow)
381706f2543Smrg    (*pScreen->ReparentWindow)(pWin, pPriorParent);
382706f2543Smrg  WIN_WRAP(ReparentWindow, winReparentWindowMultiWindow);
383706f2543Smrg
384706f2543Smrg  /* Update the Windows window associated with this X window */
385706f2543Smrg  winUpdateWindowsWindow (pWin);
386706f2543Smrg}
387706f2543Smrg
388706f2543Smrg
389706f2543Smrg/*
390706f2543Smrg * RestackWindow - Shuffle the z-order of a window
391706f2543Smrg */
392706f2543Smrg
393706f2543Smrgvoid
394706f2543SmrgwinRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib)
395706f2543Smrg{
396706f2543Smrg#if 0
397706f2543Smrg  WindowPtr		pPrevWin;
398706f2543Smrg  UINT			uFlags;
399706f2543Smrg  HWND			hInsertAfter;
400706f2543Smrg  HWND                  hWnd = NULL;
401706f2543Smrg#endif
402706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
403706f2543Smrg  winScreenPriv(pScreen);
404706f2543Smrg
405706f2543Smrg#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG
406706f2543Smrg  winTrace ("winRestackMultiWindow - %08x\n", pWin);
407706f2543Smrg#endif
408706f2543Smrg
409706f2543Smrg   WIN_UNWRAP(RestackWindow);
410706f2543Smrg   if (pScreen->RestackWindow)
411706f2543Smrg     (*pScreen->RestackWindow)(pWin, pOldNextSib);
412706f2543Smrg   WIN_WRAP(RestackWindow, winRestackWindowMultiWindow);
413706f2543Smrg
414706f2543Smrg#if 1
415706f2543Smrg  /*
416706f2543Smrg   * Calling winReorderWindowsMultiWindow here means our window manager
417706f2543Smrg   * (i.e. Windows Explorer) has initiative to determine Z order.
418706f2543Smrg   */
419706f2543Smrg  if (pWin->nextSib != pOldNextSib)
420706f2543Smrg    winReorderWindowsMultiWindow ();
421706f2543Smrg#else
422706f2543Smrg  /* Bail out if no window privates or window handle is invalid */
423706f2543Smrg  if (!pWinPriv || !pWinPriv->hWnd)
424706f2543Smrg    return;
425706f2543Smrg
426706f2543Smrg  /* Get a pointer to our previous sibling window */
427706f2543Smrg  pPrevWin = pWin->prevSib;
428706f2543Smrg
429706f2543Smrg  /*
430706f2543Smrg   * Look for a sibling window with
431706f2543Smrg   * valid privates and window handle
432706f2543Smrg   */
433706f2543Smrg  while (pPrevWin
434706f2543Smrg	 && !winGetWindowPriv(pPrevWin)
435706f2543Smrg	 && !winGetWindowPriv(pPrevWin)->hWnd)
436706f2543Smrg    pPrevWin = pPrevWin->prevSib;
437706f2543Smrg
438706f2543Smrg  /* Check if we found a valid sibling */
439706f2543Smrg  if (pPrevWin)
440706f2543Smrg    {
441706f2543Smrg      /* Valid sibling - get handle to insert window after */
442706f2543Smrg      hInsertAfter = winGetWindowPriv(pPrevWin)->hWnd;
443706f2543Smrg      uFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
444706f2543Smrg
445706f2543Smrg      hWnd = GetNextWindow (pWinPriv->hWnd, GW_HWNDPREV);
446706f2543Smrg
447706f2543Smrg      do
448706f2543Smrg	{
449706f2543Smrg	  if (GetProp (hWnd, WIN_WINDOW_PROP))
450706f2543Smrg	    {
451706f2543Smrg	      if (hWnd == winGetWindowPriv(pPrevWin)->hWnd)
452706f2543Smrg		{
453706f2543Smrg		  uFlags |= SWP_NOZORDER;
454706f2543Smrg		}
455706f2543Smrg	      break;
456706f2543Smrg	    }
457706f2543Smrg	  hWnd = GetNextWindow (hWnd, GW_HWNDPREV);
458706f2543Smrg	}
459706f2543Smrg      while (hWnd);
460706f2543Smrg    }
461706f2543Smrg  else
462706f2543Smrg    {
463706f2543Smrg      /* No valid sibling - make this window the top window */
464706f2543Smrg      hInsertAfter = HWND_TOP;
465706f2543Smrg      uFlags = SWP_NOMOVE | SWP_NOSIZE;
466706f2543Smrg    }
467706f2543Smrg
468706f2543Smrg  /* Perform the restacking operation in Windows */
469706f2543Smrg  SetWindowPos (pWinPriv->hWnd,
470706f2543Smrg		hInsertAfter,
471706f2543Smrg		0, 0,
472706f2543Smrg		0, 0,
473706f2543Smrg		uFlags);
474706f2543Smrg#endif
475706f2543Smrg}
476706f2543Smrg
477706f2543Smrg
478706f2543Smrg/*
479706f2543Smrg * winCreateWindowsWindow - Create a Windows window associated with an X window
480706f2543Smrg */
481706f2543Smrg
482706f2543Smrgvoid
483706f2543SmrgwinCreateWindowsWindow (WindowPtr pWin)
484706f2543Smrg{
485706f2543Smrg  int                   iX, iY;
486706f2543Smrg  int			iWidth;
487706f2543Smrg  int			iHeight;
488706f2543Smrg  HWND			hWnd;
489706f2543Smrg  HWND			hFore = NULL;
490706f2543Smrg  winWindowPriv(pWin);
491706f2543Smrg  HICON			hIcon;
492706f2543Smrg  HICON			hIconSmall;
493706f2543Smrg  winPrivScreenPtr	pScreenPriv = pWinPriv->pScreenPriv;
494706f2543Smrg  WinXSizeHints         hints;
495706f2543Smrg  WindowPtr		pDaddy;
496706f2543Smrg
497706f2543Smrg  winInitMultiWindowClass();
498706f2543Smrg
499706f2543Smrg#if CYGMULTIWINDOW_DEBUG
500706f2543Smrg  ErrorF ("winCreateWindowsWindow - pWin: %08x\n", pWin);
501706f2543Smrg#endif
502706f2543Smrg
503706f2543Smrg  iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
504706f2543Smrg  iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
505706f2543Smrg
506706f2543Smrg  iWidth = pWin->drawable.width;
507706f2543Smrg  iHeight = pWin->drawable.height;
508706f2543Smrg
509706f2543Smrg  /* ensure window actually ends up somewhere visible */
510706f2543Smrg  if (iX > GetSystemMetrics (SM_CXVIRTUALSCREEN))
511706f2543Smrg    iX = CW_USEDEFAULT;
512706f2543Smrg
513706f2543Smrg  if (iY > GetSystemMetrics (SM_CYVIRTUALSCREEN))
514706f2543Smrg    iY = CW_USEDEFAULT;
515706f2543Smrg
516706f2543Smrg  if (winMultiWindowGetTransientFor (pWin, &pDaddy))
517706f2543Smrg    {
518706f2543Smrg      if (pDaddy)
519706f2543Smrg      {
520706f2543Smrg        hFore = GetForegroundWindow();
521706f2543Smrg        if (hFore && (pDaddy != (WindowPtr)GetProp(hFore, WIN_WID_PROP))) hFore = NULL;
522706f2543Smrg      }
523706f2543Smrg    }
524706f2543Smrg  else
525706f2543Smrg    {
526706f2543Smrg      /* Default positions if none specified */
527706f2543Smrg      if (!winMultiWindowGetWMNormalHints(pWin, &hints))
528706f2543Smrg        hints.flags = 0;
529706f2543Smrg      if (!(hints.flags & (USPosition|PPosition)) &&
530706f2543Smrg          !pWin->overrideRedirect)
531706f2543Smrg      {
532706f2543Smrg        iX = CW_USEDEFAULT;
533706f2543Smrg        iY = CW_USEDEFAULT;
534706f2543Smrg      }
535706f2543Smrg    }
536706f2543Smrg
537706f2543Smrg  /* Create the window */
538706f2543Smrg  /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */
539706f2543Smrg  /* CW_USEDEFAULT, change back to popup after creation */
540706f2543Smrg  hWnd = CreateWindowExA (WS_EX_TOOLWINDOW,	/* Extended styles */
541706f2543Smrg			  WINDOW_CLASS_X,	/* Class name */
542706f2543Smrg			  WINDOW_TITLE_X,	/* Window name */
543706f2543Smrg			  WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
544706f2543Smrg			  iX,			/* Horizontal position */
545706f2543Smrg			  iY,			/* Vertical position */
546706f2543Smrg			  iWidth,		/* Right edge */
547706f2543Smrg			  iHeight,		/* Bottom edge */
548706f2543Smrg			  hFore,		/* Null or Parent window if transient*/
549706f2543Smrg			  (HMENU) NULL,		/* No menu */
550706f2543Smrg			  GetModuleHandle (NULL), /* Instance handle */
551706f2543Smrg			  pWin);		/* ScreenPrivates */
552706f2543Smrg  if (hWnd == NULL)
553706f2543Smrg    {
554706f2543Smrg      ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n",
555706f2543Smrg	      (int) GetLastError ());
556706f2543Smrg    }
557706f2543Smrg  pWinPriv->hWnd = hWnd;
558706f2543Smrg
559706f2543Smrg  /* Set application or .XWinrc defined Icons */
560706f2543Smrg  winSelectIcons(pWin, &hIcon, &hIconSmall);
561706f2543Smrg  if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
562706f2543Smrg  if (hIconSmall) SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
563706f2543Smrg
564706f2543Smrg  /* Change style back to popup, already placed... */
565706f2543Smrg  SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
566706f2543Smrg  SetWindowPos (hWnd, 0, 0, 0, 0, 0,
567706f2543Smrg		SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
568706f2543Smrg  /* Make sure it gets the proper system menu for a WS_POPUP, too */
569706f2543Smrg  GetSystemMenu (hWnd, TRUE);
570706f2543Smrg
571706f2543Smrg  /* Cause any .XWinrc menus to be added in main WNDPROC */
572706f2543Smrg  PostMessage (hWnd, WM_INIT_SYS_MENU, 0, 0);
573706f2543Smrg
574706f2543Smrg  SetProp (hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin));
575706f2543Smrg
576706f2543Smrg  /* Flag that this Windows window handles its own activation */
577706f2543Smrg  SetProp (hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0);
578706f2543Smrg
579706f2543Smrg  /* Call engine-specific create window procedure */
580706f2543Smrg  (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin);
581706f2543Smrg}
582706f2543Smrg
583706f2543Smrg
584706f2543SmrgBool winInDestroyWindowsWindow = FALSE;
585706f2543Smrg/*
586706f2543Smrg * winDestroyWindowsWindow - Destroy a Windows window associated
587706f2543Smrg * with an X window
588706f2543Smrg */
589706f2543Smrgstatic void
590706f2543SmrgwinDestroyWindowsWindow (WindowPtr pWin)
591706f2543Smrg{
592706f2543Smrg  MSG			msg;
593706f2543Smrg  winWindowPriv(pWin);
594706f2543Smrg  BOOL			oldstate = winInDestroyWindowsWindow;
595706f2543Smrg
596706f2543Smrg#if CYGMULTIWINDOW_DEBUG
597706f2543Smrg  ErrorF ("winDestroyWindowsWindow\n");
598706f2543Smrg#endif
599706f2543Smrg
600706f2543Smrg  /* Bail out if the Windows window handle is invalid */
601706f2543Smrg  if (pWinPriv->hWnd == NULL)
602706f2543Smrg    return;
603706f2543Smrg
604706f2543Smrg  winInDestroyWindowsWindow = TRUE;
605706f2543Smrg
606706f2543Smrg  SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, NULL);
607706f2543Smrg  /* Destroy the Windows window */
608706f2543Smrg  DestroyWindow (pWinPriv->hWnd);
609706f2543Smrg
610706f2543Smrg  /* Null our handle to the Window so referencing it will cause an error */
611706f2543Smrg  pWinPriv->hWnd = NULL;
612706f2543Smrg
613706f2543Smrg  /* Process all messages on our queue */
614706f2543Smrg  while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
615706f2543Smrg    {
616706f2543Smrg      if (g_hDlgDepthChange == 0 || !IsDialogMessage (g_hDlgDepthChange, &msg))
617706f2543Smrg	{
618706f2543Smrg	  DispatchMessage (&msg);
619706f2543Smrg	}
620706f2543Smrg    }
621706f2543Smrg
622706f2543Smrg  winInDestroyWindowsWindow = oldstate;
623706f2543Smrg
624706f2543Smrg#if CYGMULTIWINDOW_DEBUG
625706f2543Smrg  ErrorF ("-winDestroyWindowsWindow\n");
626706f2543Smrg#endif
627706f2543Smrg}
628706f2543Smrg
629706f2543Smrg
630706f2543Smrg/*
631706f2543Smrg * winUpdateWindowsWindow - Redisplay/redraw a Windows window
632706f2543Smrg * associated with an X window
633706f2543Smrg */
634706f2543Smrg
635706f2543Smrgstatic void
636706f2543SmrgwinUpdateWindowsWindow (WindowPtr pWin)
637706f2543Smrg{
638706f2543Smrg  winWindowPriv(pWin);
639706f2543Smrg  HWND			hWnd = pWinPriv->hWnd;
640706f2543Smrg
641706f2543Smrg#if CYGMULTIWINDOW_DEBUG
642706f2543Smrg  ErrorF ("winUpdateWindowsWindow\n");
643706f2543Smrg#endif
644706f2543Smrg
645706f2543Smrg  /* Check if the Windows window's parents have been destroyed */
646706f2543Smrg  if (pWin->parent != NULL
647706f2543Smrg      && pWin->parent->parent == NULL
648706f2543Smrg      && pWin->mapped)
649706f2543Smrg    {
650706f2543Smrg      /* Create the Windows window if it has been destroyed */
651706f2543Smrg      if (hWnd == NULL)
652706f2543Smrg	{
653706f2543Smrg	  winCreateWindowsWindow (pWin);
654706f2543Smrg	  assert (pWinPriv->hWnd != NULL);
655706f2543Smrg	}
656706f2543Smrg
657706f2543Smrg      /* Display the window without activating it */
658706f2543Smrg      ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE);
659706f2543Smrg
660706f2543Smrg      /* Send first paint message */
661706f2543Smrg      UpdateWindow (pWinPriv->hWnd);
662706f2543Smrg    }
663706f2543Smrg  else if (hWnd != NULL)
664706f2543Smrg    {
665706f2543Smrg      /* Destroy the Windows window if its parents are destroyed */
666706f2543Smrg      winDestroyWindowsWindow (pWin);
667706f2543Smrg      assert (pWinPriv->hWnd == NULL);
668706f2543Smrg    }
669706f2543Smrg
670706f2543Smrg#if CYGMULTIWINDOW_DEBUG
671706f2543Smrg  ErrorF ("-winUpdateWindowsWindow\n");
672706f2543Smrg#endif
673706f2543Smrg}
674706f2543Smrg
675706f2543Smrg
676706f2543Smrg/*
677706f2543Smrg * winGetWindowID -
678706f2543Smrg */
679706f2543Smrg
680706f2543SmrgXID
681706f2543SmrgwinGetWindowID (WindowPtr pWin)
682706f2543Smrg{
683706f2543Smrg  WindowIDPairRec	wi = {pWin, 0};
684706f2543Smrg  ClientPtr		c = wClient(pWin);
685706f2543Smrg
686706f2543Smrg  /* */
687706f2543Smrg  FindClientResourcesByType (c, RT_WINDOW, winFindWindow, &wi);
688706f2543Smrg
689706f2543Smrg#if CYGMULTIWINDOW_DEBUG
690706f2543Smrg  ErrorF ("winGetWindowID - Window ID: %d\n", wi.id);
691706f2543Smrg#endif
692706f2543Smrg
693706f2543Smrg  return wi.id;
694706f2543Smrg}
695706f2543Smrg
696706f2543Smrg
697706f2543Smrg/*
698706f2543Smrg * winFindWindow -
699706f2543Smrg */
700706f2543Smrg
701706f2543Smrgstatic void
702706f2543SmrgwinFindWindow (pointer value, XID id, pointer cdata)
703706f2543Smrg{
704706f2543Smrg  WindowIDPairPtr	wi = (WindowIDPairPtr)cdata;
705706f2543Smrg
706706f2543Smrg  if (value == wi->value)
707706f2543Smrg    {
708706f2543Smrg      wi->id = id;
709706f2543Smrg    }
710706f2543Smrg}
711706f2543Smrg
712706f2543Smrg
713706f2543Smrg/*
714706f2543Smrg * winReorderWindowsMultiWindow -
715706f2543Smrg */
716706f2543Smrg
717706f2543Smrgvoid
718706f2543SmrgwinReorderWindowsMultiWindow (void)
719706f2543Smrg{
720706f2543Smrg  HWND hwnd = NULL;
721706f2543Smrg  WindowPtr pWin = NULL;
722706f2543Smrg  WindowPtr pWinSib = NULL;
723706f2543Smrg  XID vlist[2];
724706f2543Smrg  static Bool fRestacking = FALSE; /* Avoid recusive calls to this function */
725706f2543Smrg  DWORD dwCurrentProcessID = GetCurrentProcessId ();
726706f2543Smrg  DWORD dwWindowProcessID = 0;
727706f2543Smrg
728706f2543Smrg#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG
729706f2543Smrg  winTrace ("winReorderWindowsMultiWindow\n");
730706f2543Smrg#endif
731706f2543Smrg
732706f2543Smrg  if (fRestacking)
733706f2543Smrg    {
734706f2543Smrg      /* It is a recusive call so immediately exit */
735706f2543Smrg#if CYGWINDOWING_DEBUG
736706f2543Smrg      ErrorF ("winReorderWindowsMultiWindow - "
737706f2543Smrg	      "exit because fRestacking == TRUE\n");
738706f2543Smrg#endif
739706f2543Smrg      return;
740706f2543Smrg    }
741706f2543Smrg  fRestacking = TRUE;
742706f2543Smrg
743706f2543Smrg  /* Loop through top level Window windows, descending in Z order */
744706f2543Smrg  for ( hwnd = GetTopWindow (NULL);
745706f2543Smrg	hwnd;
746706f2543Smrg	hwnd = GetNextWindow (hwnd, GW_HWNDNEXT) )
747706f2543Smrg    {
748706f2543Smrg      /* Don't take care of other Cygwin/X process's windows */
749706f2543Smrg      GetWindowThreadProcessId (hwnd, &dwWindowProcessID);
750706f2543Smrg
751706f2543Smrg      if ( GetProp (hwnd, WIN_WINDOW_PROP)
752706f2543Smrg	   && (dwWindowProcessID == dwCurrentProcessID)
753706f2543Smrg	   && !IsIconic (hwnd) ) /* ignore minimized windows */
754706f2543Smrg	{
755706f2543Smrg	  pWinSib = pWin;
756706f2543Smrg	  pWin = GetProp (hwnd, WIN_WINDOW_PROP);
757706f2543Smrg
758706f2543Smrg	  if (!pWinSib)
759706f2543Smrg	    { /* 1st window - raise to the top */
760706f2543Smrg	      vlist[0] = Above;
761706f2543Smrg
762706f2543Smrg	      ConfigureWindow (pWin, CWStackMode, vlist, wClient(pWin));
763706f2543Smrg	    }
764706f2543Smrg	  else
765706f2543Smrg	    { /* 2nd or deeper windows - just below the previous one */
766706f2543Smrg	      vlist[0] = winGetWindowID (pWinSib);
767706f2543Smrg	      vlist[1] = Below;
768706f2543Smrg
769706f2543Smrg	      ConfigureWindow (pWin, CWSibling | CWStackMode,
770706f2543Smrg			       vlist, wClient(pWin));
771706f2543Smrg	    }
772706f2543Smrg	}
773706f2543Smrg    }
774706f2543Smrg
775706f2543Smrg  fRestacking = FALSE;
776706f2543Smrg}
777706f2543Smrg
778706f2543Smrg
779706f2543Smrg/*
780706f2543Smrg * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE
781706f2543Smrg */
782706f2543Smrg
783706f2543Smrgvoid
784706f2543SmrgwinMinimizeWindow (Window id)
785706f2543Smrg{
786706f2543Smrg  WindowPtr		pWin;
787706f2543Smrg  winPrivWinPtr	pWinPriv;
788706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
789706f2543Smrg  win32RootlessWindowPtr pRLWinPriv;
790706f2543Smrg#endif
791706f2543Smrg  HWND hWnd;
792706f2543Smrg  ScreenPtr pScreen = NULL;
793706f2543Smrg  winPrivScreenPtr pScreenPriv = NULL;
794706f2543Smrg  winScreenInfo *pScreenInfo = NULL;
795706f2543Smrg
796706f2543Smrg#if CYGWINDOWING_DEBUG
797706f2543Smrg  ErrorF ("winMinimizeWindow\n");
798706f2543Smrg#endif
799706f2543Smrg
800706f2543Smrg  dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, DixUnknownAccess);
801706f2543Smrg  if (!pWin)
802706f2543Smrg  {
803706f2543Smrg      ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__);
804706f2543Smrg      return;
805706f2543Smrg  }
806706f2543Smrg
807706f2543Smrg  pScreen = pWin->drawable.pScreen;
808706f2543Smrg  if (pScreen) pScreenPriv = winGetScreenPriv(pScreen);
809706f2543Smrg  if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
810706f2543Smrg
811706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
812706f2543Smrg  if (pScreenPriv && pScreenInfo->fInternalWM)
813706f2543Smrg    {
814706f2543Smrg      pRLWinPriv  = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
815706f2543Smrg      hWnd = pRLWinPriv->hWnd;
816706f2543Smrg    }
817706f2543Smrg  else
818706f2543Smrg#else
819706f2543Smrg  if (pScreenPriv)
820706f2543Smrg#endif
821706f2543Smrg    {
822706f2543Smrg      pWinPriv = winGetWindowPriv (pWin);
823706f2543Smrg      hWnd = pWinPriv->hWnd;
824706f2543Smrg    }
825706f2543Smrg
826706f2543Smrg  ShowWindow (hWnd, SW_MINIMIZE);
827706f2543Smrg}
828706f2543Smrg
829706f2543Smrg
830706f2543Smrg/*
831706f2543Smrg * CopyWindow - See Porting Layer Definition - p. 39
832706f2543Smrg */
833706f2543Smrgvoid
834706f2543SmrgwinCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt,
835706f2543Smrg			  RegionPtr oldRegion)
836706f2543Smrg{
837706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
838706f2543Smrg  winScreenPriv(pScreen);
839706f2543Smrg
840706f2543Smrg#if CYGWINDOWING_DEBUG
841706f2543Smrg  ErrorF ("CopyWindowMultiWindow\n");
842706f2543Smrg#endif
843706f2543Smrg  WIN_UNWRAP(CopyWindow);
844706f2543Smrg  (*pScreen->CopyWindow)(pWin, oldpt, oldRegion);
845706f2543Smrg  WIN_WRAP(CopyWindow, winCopyWindowMultiWindow);
846706f2543Smrg}
847706f2543Smrg
848706f2543Smrg
849706f2543Smrg/*
850706f2543Smrg * MoveWindow - See Porting Layer Definition - p. 42
851706f2543Smrg */
852706f2543Smrgvoid
853706f2543SmrgwinMoveWindowMultiWindow (WindowPtr pWin, int x, int y,
854706f2543Smrg			  WindowPtr pSib, VTKind kind)
855706f2543Smrg{
856706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
857706f2543Smrg  winScreenPriv(pScreen);
858706f2543Smrg
859706f2543Smrg#if CYGWINDOWING_DEBUG
860706f2543Smrg  ErrorF ("MoveWindowMultiWindow to (%d, %d)\n", x, y);
861706f2543Smrg#endif
862706f2543Smrg
863706f2543Smrg  WIN_UNWRAP(MoveWindow);
864706f2543Smrg  (*pScreen->MoveWindow)(pWin, x, y, pSib, kind);
865706f2543Smrg  WIN_WRAP(MoveWindow, winMoveWindowMultiWindow);
866706f2543Smrg}
867706f2543Smrg
868706f2543Smrg
869706f2543Smrg/*
870706f2543Smrg * ResizeWindow - See Porting Layer Definition - p. 42
871706f2543Smrg */
872706f2543Smrgvoid
873706f2543SmrgwinResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w,
874706f2543Smrg			    unsigned int h, WindowPtr pSib)
875706f2543Smrg{
876706f2543Smrg  ScreenPtr		pScreen = pWin->drawable.pScreen;
877706f2543Smrg  winScreenPriv(pScreen);
878706f2543Smrg
879706f2543Smrg#if CYGWINDOWING_DEBUG
880706f2543Smrg  ErrorF ("ResizeWindowMultiWindow to (%d, %d) - %dx%d\n", x, y, w, h);
881706f2543Smrg#endif
882706f2543Smrg  WIN_UNWRAP(ResizeWindow);
883706f2543Smrg  (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
884706f2543Smrg  WIN_WRAP(ResizeWindow, winResizeWindowMultiWindow);
885706f2543Smrg}
886706f2543Smrg
887706f2543Smrg
888706f2543Smrg/*
889706f2543Smrg * winAdjustXWindow
890706f2543Smrg *
891706f2543Smrg * Move and resize X window with respect to corresponding Windows window.
892706f2543Smrg * This is called from WM_MOVE/WM_SIZE handlers when the user performs
893706f2543Smrg * any windowing operation (move, resize, minimize, maximize, restore).
894706f2543Smrg *
895706f2543Smrg * The functionality is the inverse of winPositionWindowMultiWindow, which
896706f2543Smrg * adjusts Windows window with respect to X window.
897706f2543Smrg */
898706f2543Smrgint
899706f2543SmrgwinAdjustXWindow (WindowPtr pWin, HWND hwnd)
900706f2543Smrg{
901706f2543Smrg  RECT rcDraw; /* Rect made from pWin->drawable to be adjusted */
902706f2543Smrg  RECT rcWin;  /* The source: WindowRect from hwnd */
903706f2543Smrg  DrawablePtr pDraw;
904706f2543Smrg  XID vlist[4];
905706f2543Smrg  LONG dX, dY, dW, dH, x, y;
906706f2543Smrg  DWORD dwStyle, dwExStyle;
907706f2543Smrg
908706f2543Smrg#define WIDTH(rc) (rc.right - rc.left)
909706f2543Smrg#define HEIGHT(rc) (rc.bottom - rc.top)
910706f2543Smrg
911706f2543Smrg#if CYGWINDOWING_DEBUG
912706f2543Smrg  ErrorF ("winAdjustXWindow\n");
913706f2543Smrg#endif
914706f2543Smrg
915706f2543Smrg  if (IsIconic (hwnd))
916706f2543Smrg    {
917706f2543Smrg#if CYGWINDOWING_DEBUG
918706f2543Smrg      ErrorF ("\timmediately return because the window is iconized\n");
919706f2543Smrg#endif
920706f2543Smrg      /*
921706f2543Smrg       * If the Windows window is minimized, its WindowRect has
922706f2543Smrg       * meaningless values so we don't adjust X window to it.
923706f2543Smrg       */
924706f2543Smrg      vlist[0] = 0;
925706f2543Smrg      vlist[1] = 0;
926706f2543Smrg      return ConfigureWindow (pWin, CWX | CWY, vlist, wClient(pWin));
927706f2543Smrg    }
928706f2543Smrg
929706f2543Smrg  pDraw = &pWin->drawable;
930706f2543Smrg
931706f2543Smrg  /* Calculate the window rect from the drawable */
932706f2543Smrg  x = pDraw->x + GetSystemMetrics (SM_XVIRTUALSCREEN);
933706f2543Smrg  y = pDraw->y + GetSystemMetrics (SM_YVIRTUALSCREEN);
934706f2543Smrg  SetRect (&rcDraw, x, y, x + pDraw->width, y + pDraw->height);
935706f2543Smrg#ifdef CYGMULTIWINDOW_DEBUG
936706f2543Smrg          winDebug("\tDrawable extend {%d, %d, %d, %d}, {%d, %d}\n",
937706f2543Smrg              rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom,
938706f2543Smrg              rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top);
939706f2543Smrg#endif
940706f2543Smrg  dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE);
941706f2543Smrg  dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE);
942706f2543Smrg#ifdef CYGMULTIWINDOW_DEBUG
943706f2543Smrg          winDebug("\tWindowStyle: %08x %08x\n", dwStyle, dwExStyle);
944706f2543Smrg#endif
945706f2543Smrg  AdjustWindowRectEx (&rcDraw, dwStyle, FALSE, dwExStyle);
946706f2543Smrg
947706f2543Smrg  /* The source of adjust */
948706f2543Smrg  GetWindowRect (hwnd, &rcWin);
949706f2543Smrg#ifdef CYGMULTIWINDOW_DEBUG
950706f2543Smrg          winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n",
951706f2543Smrg              rcWin.left, rcWin.top, rcWin.right, rcWin.bottom,
952706f2543Smrg              rcWin.right - rcWin.left, rcWin.bottom - rcWin.top);
953706f2543Smrg          winDebug("\tDraw extend {%d, %d, %d, %d}, {%d, %d}\n",
954706f2543Smrg              rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom,
955706f2543Smrg              rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top);
956706f2543Smrg#endif
957706f2543Smrg
958706f2543Smrg  if (EqualRect (&rcDraw, &rcWin)) {
959706f2543Smrg    /* Bail if no adjust is needed */
960706f2543Smrg#if CYGWINDOWING_DEBUG
961706f2543Smrg    ErrorF ("\treturn because already adjusted\n");
962706f2543Smrg#endif
963706f2543Smrg    return 0;
964706f2543Smrg  }
965706f2543Smrg
966706f2543Smrg  /* Calculate delta values */
967706f2543Smrg  dX = rcWin.left - rcDraw.left;
968706f2543Smrg  dY = rcWin.top - rcDraw.top;
969706f2543Smrg  dW = WIDTH(rcWin) - WIDTH(rcDraw);
970706f2543Smrg  dH = HEIGHT(rcWin) - HEIGHT(rcDraw);
971706f2543Smrg
972706f2543Smrg  /*
973706f2543Smrg   * Adjust.
974706f2543Smrg   * We may only need to move (vlist[0] and [1]), or only resize
975706f2543Smrg   * ([2] and [3]) but currently we set all the parameters and leave
976706f2543Smrg   * the decision to ConfigureWindow.  The reason is code simplicity.
977706f2543Smrg  */
978706f2543Smrg  vlist[0] = pDraw->x + dX - wBorderWidth(pWin);
979706f2543Smrg  vlist[1] = pDraw->y + dY - wBorderWidth(pWin);
980706f2543Smrg  vlist[2] = pDraw->width + dW;
981706f2543Smrg  vlist[3] = pDraw->height + dH;
982706f2543Smrg#if CYGWINDOWING_DEBUG
983706f2543Smrg  ErrorF ("\tConfigureWindow to (%ld, %ld) - %ldx%ld\n", vlist[0], vlist[1],
984706f2543Smrg	  vlist[2], vlist[3]);
985706f2543Smrg#endif
986706f2543Smrg  return ConfigureWindow (pWin, CWX | CWY | CWWidth | CWHeight,
987706f2543Smrg			  vlist, wClient(pWin));
988706f2543Smrg
989706f2543Smrg#undef WIDTH
990706f2543Smrg#undef HEIGHT
991706f2543Smrg}
992706f2543Smrg
993