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