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