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