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