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 48void 49 winCreateWindowsWindow(WindowPtr pWin); 50 51static void 52 winDestroyWindowsWindow(WindowPtr pWin); 53 54static void 55 winUpdateWindowsWindow(WindowPtr pWin); 56 57static void 58 winFindWindow(void *value, XID id, void *cdata); 59 60static 61 void 62winInitMultiWindowClass(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 99Bool 100winCreateWindowMultiWindow(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 132Bool 133winDestroyWindowMultiWindow(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 166Bool 167winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) 168{ 169 Bool fResult = TRUE; 170 int iX, iY, iWidth, iHeight; 171 ScreenPtr pScreen = pWin->drawable.pScreen; 172 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 282Bool 283winChangeWindowAttributesMultiWindow(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 310Bool 311winUnmapWindowMultiWindow(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 341Bool 342winMapWindowMultiWindow(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 375void 376winReparentWindowMultiWindow(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 401void 402winRestackWindowMultiWindow(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 480void 481winCreateWindowsWindow(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 its 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 preserve 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 612Bool winInDestroyWindowsWindow = FALSE; 613 614/* 615 * winDestroyWindowsWindow - Destroy a Windows window associated 616 * with an X window 617 */ 618static void 619winDestroyWindowsWindow(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 673static void 674winUpdateWindowsWindow(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 713XID 714winGetWindowID(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 733static void 734winFindWindow(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 747void 748winReorderWindowsMultiWindow(void) 749{ 750 HWND hwnd = NULL; 751 WindowPtr pWin = NULL; 752 WindowPtr pWinSib = NULL; 753 XID vlist[2]; 754 static Bool fRestacking = FALSE; /* Avoid recursive 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 recursive 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 */ 805void 806winCopyWindowMultiWindow(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 */ 823void 824winMoveWindowMultiWindow(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 */ 843void 844winResizeWindowMultiWindow(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 */ 869int 870winAdjustXWindow(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 964/* 965 Helper function for creating a DIB to back a pixmap 966 */ 967static HBITMAP winCreateDIB(ScreenPtr pScreen, int width, int height, int bpp, void **ppvBits, BITMAPINFOHEADER **ppbmih) 968{ 969 winScreenPriv(pScreen); 970 BITMAPV4HEADER *pbmih = NULL; 971 HBITMAP hBitmap = NULL; 972 973 /* Allocate bitmap info header */ 974 pbmih = malloc(sizeof(BITMAPV4HEADER) + 256 * sizeof(RGBQUAD)); 975 if (pbmih == NULL) { 976 ErrorF("winCreateDIB: malloc() failed\n"); 977 return NULL; 978 } 979 memset(pbmih, 0, sizeof(BITMAPV4HEADER) + 256 * sizeof(RGBQUAD)); 980 981 /* Describe bitmap to be created */ 982 pbmih->bV4Size = sizeof(BITMAPV4HEADER); 983 pbmih->bV4Width = width; 984 pbmih->bV4Height = -height; /* top-down bitmap */ 985 pbmih->bV4Planes = 1; 986 pbmih->bV4BitCount = bpp; 987 if (bpp == 1) { 988 RGBQUAD *bmiColors = (RGBQUAD *)((char *)pbmih + sizeof(BITMAPV4HEADER)); 989 pbmih->bV4V4Compression = BI_RGB; 990 bmiColors[1].rgbBlue = 255; 991 bmiColors[1].rgbGreen = 255; 992 bmiColors[1].rgbRed = 255; 993 } 994 else if (bpp == 8) { 995 pbmih->bV4V4Compression = BI_RGB; 996 pbmih->bV4ClrUsed = 0; 997 } 998 else if (bpp == 16) { 999 pbmih->bV4V4Compression = BI_RGB; 1000 pbmih->bV4ClrUsed = 0; 1001 } 1002 else if (bpp == 32) { 1003 pbmih->bV4V4Compression = BI_BITFIELDS; 1004 pbmih->bV4RedMask = pScreenPriv->dwRedMask; 1005 pbmih->bV4GreenMask = pScreenPriv->dwGreenMask; 1006 pbmih->bV4BlueMask = pScreenPriv->dwBlueMask; 1007 pbmih->bV4AlphaMask = 0; 1008 } 1009 else { 1010 ErrorF("winCreateDIB: %d bpp unhandled\n", bpp); 1011 } 1012 1013 /* Create a DIB with a bit pointer */ 1014 hBitmap = CreateDIBSection(NULL, 1015 (BITMAPINFO *) pbmih, 1016 DIB_RGB_COLORS, ppvBits, NULL, 0); 1017 if (hBitmap == NULL) { 1018 ErrorF("winCreateDIB: CreateDIBSection() failed\n"); 1019 return NULL; 1020 } 1021 1022 /* Store the address of the BMIH in the ppbmih parameter */ 1023 *ppbmih = (BITMAPINFOHEADER *)pbmih; 1024 1025 winDebug("winCreateDIB: HBITMAP %p pBMIH %p pBits %p\n", hBitmap, pbmih, *ppvBits); 1026 1027 return hBitmap; 1028} 1029 1030 1031/* 1032 * CreatePixmap - See Porting Layer Definition 1033 */ 1034PixmapPtr 1035winCreatePixmapMultiwindow(ScreenPtr pScreen, int width, int height, int depth, 1036 unsigned usage_hint) 1037{ 1038 winPrivPixmapPtr pPixmapPriv = NULL; 1039 PixmapPtr pPixmap = NULL; 1040 int bpp, paddedwidth; 1041 1042 /* allocate Pixmap header and privates */ 1043 pPixmap = AllocatePixmap(pScreen, 0); 1044 if (!pPixmap) 1045 return NullPixmap; 1046 1047 bpp = BitsPerPixel(depth); 1048 /* 1049 DIBs have 4-byte aligned rows 1050 1051 paddedwidth is the width in bytes, padded to align 1052 1053 i.e. round up the number of bits used by a row so it is a multiple of 32, 1054 then convert to bytes 1055 */ 1056 paddedwidth = (((bpp * width) + 31) & ~31)/8; 1057 1058 /* setup Pixmap header */ 1059 pPixmap->drawable.type = DRAWABLE_PIXMAP; 1060 pPixmap->drawable.class = 0; 1061 pPixmap->drawable.pScreen = pScreen; 1062 pPixmap->drawable.depth = depth; 1063 pPixmap->drawable.bitsPerPixel = bpp; 1064 pPixmap->drawable.id = 0; 1065 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1066 pPixmap->drawable.x = 0; 1067 pPixmap->drawable.y = 0; 1068 pPixmap->drawable.width = width; 1069 pPixmap->drawable.height = height; 1070 pPixmap->devKind = paddedwidth; 1071 pPixmap->refcnt = 1; 1072 pPixmap->devPrivate.ptr = NULL; // later set to pbBits 1073 pPixmap->primary_pixmap = NULL; 1074#ifdef COMPOSITE 1075 pPixmap->screen_x = 0; 1076 pPixmap->screen_y = 0; 1077#endif 1078 pPixmap->usage_hint = usage_hint; 1079 1080 /* Check for zero width or height pixmaps */ 1081 if (width == 0 || height == 0) { 1082 /* DIBs with a dimension of 0 aren't permitted, so don't try to allocate 1083 a DIB, just set fields and return */ 1084 return pPixmap; 1085 } 1086 1087 /* Initialize pixmap privates */ 1088 pPixmapPriv = winGetPixmapPriv(pPixmap); 1089 pPixmapPriv->hBitmap = NULL; 1090 pPixmapPriv->pbBits = NULL; 1091 pPixmapPriv->pbmih = NULL; 1092 1093 /* Create a DIB for the pixmap */ 1094 pPixmapPriv->hBitmap = winCreateDIB(pScreen, width, height, bpp, &pPixmapPriv->pbBits, &pPixmapPriv->pbmih); 1095 pPixmapPriv->owned = TRUE; 1096 1097 winDebug("winCreatePixmap: pPixmap %p HBITMAP %p pBMIH %p pBits %p\n", pPixmap, pPixmapPriv->hBitmap, pPixmapPriv->pbmih, pPixmapPriv->pbBits); 1098 /* XXX: so why do we need this in privates ??? */ 1099 pPixmap->devPrivate.ptr = pPixmapPriv->pbBits; 1100 1101 return pPixmap; 1102} 1103 1104/* 1105 * DestroyPixmap - See Porting Layer Definition 1106 */ 1107Bool 1108winDestroyPixmapMultiwindow(PixmapPtr pPixmap) 1109{ 1110 winPrivPixmapPtr pPixmapPriv = NULL; 1111 1112 /* Bail early if there is not a pixmap to destroy */ 1113 if (pPixmap == NULL) { 1114 return TRUE; 1115 } 1116 1117 /* Decrement reference count, return if nonzero */ 1118 --pPixmap->refcnt; 1119 if (pPixmap->refcnt != 0) 1120 return TRUE; 1121 1122 winDebug("winDestroyPixmap: pPixmap %p\n", pPixmap); 1123 1124 /* Get a handle to the pixmap privates */ 1125 pPixmapPriv = winGetPixmapPriv(pPixmap); 1126 1127 /* Nothing to do if we don't own the DIB */ 1128 if (!pPixmapPriv->owned) 1129 return TRUE; 1130 1131 /* Free GDI bitmap */ 1132 if (pPixmapPriv->hBitmap) 1133 DeleteObject(pPixmapPriv->hBitmap); 1134 1135 /* Free the bitmap info header memory */ 1136 free(pPixmapPriv->pbmih); 1137 pPixmapPriv->pbmih = NULL; 1138 1139 /* Free the pixmap memory */ 1140 free(pPixmap); 1141 pPixmap = NULL; 1142 1143 return TRUE; 1144} 1145 1146/* 1147 * ModifyPixmapHeader - See Porting Layer Definition 1148 */ 1149Bool 1150winModifyPixmapHeaderMultiwindow(PixmapPtr pPixmap, 1151 int width, 1152 int height, 1153 int depth, 1154 int bitsPerPixel, int devKind, void *pPixData) 1155{ 1156 int i; 1157 winPrivPixmapPtr pPixmapPriv = winGetPixmapPriv(pPixmap); 1158 Bool fResult; 1159 1160 /* reinitialize everything */ 1161 pPixmap->drawable.depth = depth; 1162 pPixmap->drawable.bitsPerPixel = bitsPerPixel; 1163 pPixmap->drawable.id = 0; 1164 pPixmap->drawable.x = 0; 1165 pPixmap->drawable.y = 0; 1166 pPixmap->drawable.width = width; 1167 pPixmap->drawable.height = height; 1168 pPixmap->devKind = devKind; 1169 pPixmap->refcnt = 1; 1170 pPixmap->devPrivate.ptr = pPixData; 1171 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1172 1173 /* 1174 This can be used for some out-of-order initialization on the screen 1175 pixmap, which is the only case we can properly support. 1176 */ 1177 1178 /* Look for which screen this pixmap corresponds to */ 1179 for (i = 0; i < screenInfo.numScreens; i++) { 1180 ScreenPtr pScreen = screenInfo.screens[i]; 1181 winScreenPriv(pScreen); 1182 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 1183 1184 if (pScreenInfo->pfb == pPixData) 1185 { 1186 /* and initialize pixmap privates from screen privates */ 1187 pPixmapPriv->hBitmap = pScreenPriv->hbmpShadow; 1188 pPixmapPriv->pbBits = pScreenInfo->pfb; 1189 pPixmapPriv->pbmih = pScreenPriv->pbmih; 1190 1191 /* mark these not to get released by DestroyPixmap */ 1192 pPixmapPriv->owned = FALSE; 1193 1194 return TRUE; 1195 } 1196 } 1197 1198 /* Otherwise, since creating a DIBSection from arbitrary memory is not 1199 * possible, fallback to normal. If needed, we can create a DIBSection with 1200 * a copy of the bits later (see comment about a potential slow-path in 1201 * winBltExposedWindowRegionShadowGDI()). */ 1202 pPixmapPriv->hBitmap = 0; 1203 pPixmapPriv->pbBits = 0; 1204 pPixmapPriv->pbmih = 0; 1205 pPixmapPriv->owned = FALSE; 1206 1207 winDebug("winModifyPixmapHeaderMultiwindow: falling back\n"); 1208 1209 { 1210 ScreenPtr pScreen = pPixmap->drawable.pScreen; 1211 winScreenPriv(pScreen); 1212 WIN_UNWRAP(ModifyPixmapHeader); 1213 fResult = (*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData); 1214 WIN_WRAP(ModifyPixmapHeader, winModifyPixmapHeaderMultiwindow); 1215 } 1216 1217 return fResult; 1218} 1219