/* *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. *Copyright (C) Colin Harrison 2005-2008 * *Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the *"Software"), to deal in the Software without restriction, including *without limitation the rights to use, copy, modify, merge, publish, *distribute, sublicense, and/or sell copies of the Software, and to *permit persons to whom the Software is furnished to do so, subject to *the following conditions: * *The above copyright notice and this permission notice shall be *included in all copies or substantial portions of the Software. * *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *Except as contained in this notice, the name of the XFree86 Project *shall not be used in advertising or otherwise to promote the sale, use *or other dealings in this Software without prior written authorization *from the XFree86 Project. * * Authors: Kensuke Matsuzaki * Earle F. Philhower, III * Harold L Hunt II * Colin Harrison */ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif #include "win.h" #include "dixevents.h" #include "winmultiwindowclass.h" #include "winprefs.h" /* * External global variables */ extern HICON g_hIconX; extern HICON g_hSmallIconX; extern HWND g_hDlgDepthChange; /* * Prototypes for local functions */ void winCreateWindowsWindow (WindowPtr pWin); static void winDestroyWindowsWindow (WindowPtr pWin); static void winUpdateWindowsWindow (WindowPtr pWin); static void winFindWindow (pointer value, XID id, pointer cdata); static void winInitMultiWindowClass(void) { static wATOM atomXWinClass=0; WNDCLASSEX wcx; if (atomXWinClass==0) { /* Setup our window class */ wcx.cbSize=sizeof(WNDCLASSEX); wcx.style = CS_HREDRAW | CS_VREDRAW; wcx.lpfnWndProc = winTopLevelWindowProc; wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; wcx.hInstance = g_hInstance; wcx.hIcon = g_hIconX; wcx.hCursor = 0; wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wcx.lpszMenuName = NULL; wcx.lpszClassName = WINDOW_CLASS_X; wcx.hIconSm = g_hSmallIconX; #if CYGMULTIWINDOW_DEBUG winDebug ("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X); #endif atomXWinClass = RegisterClassEx (&wcx); } } /* * CreateWindow - See Porting Layer Definition - p. 37 */ Bool winCreateWindowMultiWindow (WindowPtr pWin) { Bool fResult = TRUE; ScreenPtr pScreen = pWin->drawable.pScreen; winWindowPriv(pWin); winScreenPriv(pScreen); #if CYGMULTIWINDOW_DEBUG winDebug ("winCreateWindowMultiWindow - pWin: %p\n", pWin); #endif WIN_UNWRAP(CreateWindow); fResult = (*pScreen->CreateWindow) (pWin); WIN_WRAP(CreateWindow, winCreateWindowMultiWindow); /* Initialize some privates values */ pWinPriv->hRgn = NULL; pWinPriv->hWnd = NULL; pWinPriv->GlCtxWnd = FALSE; pWinPriv->pScreenPriv = winGetScreenPriv(pWin->drawable.pScreen); pWinPriv->fXKilled = FALSE; return fResult; } /* * DestroyWindow - See Porting Layer Definition - p. 37 */ Bool winDestroyWindowMultiWindow (WindowPtr pWin) { Bool fResult = TRUE; ScreenPtr pScreen = pWin->drawable.pScreen; winWindowPriv(pWin); winScreenPriv(pScreen); #if CYGMULTIWINDOW_DEBUG winDebug ("winDestroyWindowMultiWindow - pWin: %p\n", pWin); #endif WIN_UNWRAP(DestroyWindow); fResult = (*pScreen->DestroyWindow)(pWin); WIN_WRAP(DestroyWindow, winDestroyWindowMultiWindow); /* Flag that the window has been destroyed */ pWinPriv->fXKilled = TRUE; /* Kill the MS Windows window associated with this window */ winDestroyWindowsWindow (pWin); return fResult; } /* * PositionWindow - See Porting Layer Definition - p. 37 * * This function adjusts the position and size of Windows window * with respect to the underlying X window. This is the inverse * of winAdjustXWindow, which adjusts X window to Windows window. */ Bool winPositionWindowMultiWindow (WindowPtr pWin, int x, int y) { Bool fResult = TRUE; int iX, iY, iWidth, iHeight; ScreenPtr pScreen = pWin->drawable.pScreen; winWindowPriv(pWin); winScreenPriv(pScreen); HWND hWnd = pWinPriv->hWnd; RECT rcNew; RECT rcOld; #ifdef WINDBG RECT rcClient; RECT *lpRc; #endif DWORD dwExStyle; DWORD dwStyle; winDebug ("winPositionWindowMultiWindow - pWin: %p\n", pWin); WIN_UNWRAP(PositionWindow); fResult = (*pScreen->PositionWindow)(pWin, x, y); WIN_WRAP(PositionWindow, winPositionWindowMultiWindow); winDebug ("winPositionWindowMultiWindow: (x, y) = (%d, %d)\n", x, y); /* Bail out if the Windows window handle is bad */ if (!hWnd) { winDebug ("\timmediately return since hWnd is NULL\n"); return fResult; } /* Get the Windows window style and extended style */ dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE); dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE); /* Get the X and Y location of the X window */ iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN); iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN); /* Get the height and width of the X window */ iWidth = pWin->drawable.width; iHeight = pWin->drawable.height; /* Store the origin, height, and width in a rectangle structure */ SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight); #if CYGMULTIWINDOW_DEBUG lpRc = &rcNew; winDebug ("winPositionWindowMultiWindow - (%d ms)drawable (%d, %d)-(%d, %d)\n", GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); #endif /* * Calculate the required size of the Windows window rectangle, * given the size of the Windows window client area. */ AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle); /* Get a rectangle describing the old Windows window */ GetWindowRect (hWnd, &rcOld); #if CYGMULTIWINDOW_DEBUG /* Get a rectangle describing the Windows window client area */ GetClientRect (hWnd, &rcClient); lpRc = &rcNew; winDebug ("winPositionWindowMultiWindow - (%d ms)rcNew (%d, %d)-(%d, %d)\n", GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); lpRc = &rcOld; winDebug ("winPositionWindowMultiWindow - (%d ms)rcOld (%d, %d)-(%d, %d)\n", GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); lpRc = &rcClient; winDebug ("(%d ms)rcClient (%d, %d)-(%d, %d)\n", GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); #endif /* Check if the old rectangle and new rectangle are the same */ if (!EqualRect (&rcNew, &rcOld)) { winDebug ("winPositionWindowMultiWindow - Need to move\n"); winDebug ("\tMoveWindow to (%ld, %ld) - %ldx%ld\n", rcNew.left, rcNew.top, rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); /* Change the position and dimensions of the Windows window */ MoveWindow (hWnd, rcNew.left, rcNew.top, rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, TRUE); } else { winDebug ("winPositionWindowMultiWindow - Not need to move\n"); } return fResult; } /* * ChangeWindowAttributes - See Porting Layer Definition - p. 37 */ Bool winChangeWindowAttributesMultiWindow (WindowPtr pWin, unsigned long mask) { Bool fResult = TRUE; ScreenPtr pScreen = pWin->drawable.pScreen; winScreenPriv(pScreen); winDebug ("winChangeWindowAttributesMultiWindow - pWin: %08x\n", pWin); WIN_UNWRAP(ChangeWindowAttributes); fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask); WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesMultiWindow); /* * NOTE: We do not currently need to do anything here. */ return fResult; } /* * UnmapWindow - See Porting Layer Definition - p. 37 * Also referred to as UnrealizeWindow */ Bool winUnmapWindowMultiWindow (WindowPtr pWin) { Bool fResult = TRUE; ScreenPtr pScreen = pWin->drawable.pScreen; winWindowPriv(pWin); winScreenPriv(pScreen); #if CYGMULTIWINDOW_DEBUG winDebug ("winUnmapWindowMultiWindow - pWin: %08x\n", pWin); #endif WIN_UNWRAP(UnrealizeWindow); fResult = (*pScreen->UnrealizeWindow)(pWin); WIN_WRAP(UnrealizeWindow, winUnmapWindowMultiWindow); /* Flag that the window has been killed */ pWinPriv->fXKilled = TRUE; /* Destroy the Windows window associated with this X window */ winDestroyWindowsWindow (pWin); return fResult; } /* * MapWindow - See Porting Layer Definition - p. 37 * Also referred to as RealizeWindow */ Bool winMapWindowMultiWindow (WindowPtr pWin) { Bool fResult = TRUE; ScreenPtr pScreen = pWin->drawable.pScreen; winWindowPriv(pWin); winScreenPriv(pScreen); #if CYGMULTIWINDOW_DEBUG winDebug ("winMapWindowMultiWindow - pWin: %08x\n", pWin); #endif WIN_UNWRAP(RealizeWindow); fResult = (*pScreen->RealizeWindow)(pWin); WIN_WRAP(RealizeWindow, winMapWindowMultiWindow); /* Flag that this window has not been destroyed */ pWinPriv->fXKilled = FALSE; /* Refresh/redisplay the Windows window associated with this X window */ winUpdateWindowsWindow (pWin); /* Update the Windows window's shape */ winReshapeMultiWindow (pWin); winUpdateRgnMultiWindow (pWin); return fResult; } /* * ReparentWindow - See Porting Layer Definition - p. 42 */ void winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent) { ScreenPtr pScreen = pWin->drawable.pScreen; winScreenPriv(pScreen); #if CYGMULTIWINDOW_DEBUG winDebug ("winReparentMultiWindow - pWin: %08x\n", pWin); #endif WIN_UNWRAP(ReparentWindow); if (pScreen->ReparentWindow) (*pScreen->ReparentWindow)(pWin, pPriorParent); WIN_WRAP(ReparentWindow, winReparentWindowMultiWindow); /* Update the Windows window associated with this X window */ winUpdateWindowsWindow (pWin); } /* * RestackWindow - Shuffle the z-order of a window */ void winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib) { ScreenPtr pScreen = pWin->drawable.pScreen; winScreenPriv(pScreen); winDebug ("winRestackMultiWindow - %08x\n", pWin); WIN_UNWRAP(RestackWindow); if (pScreen->RestackWindow) (*pScreen->RestackWindow)(pWin, pOldNextSib); WIN_WRAP(RestackWindow, winRestackWindowMultiWindow); /* * Calling winReorderWindowsMultiWindow here means our window manager * (i.e. Windows Explorer) has initiative to determine Z order. */ if (pWin->nextSib != pOldNextSib) winReorderWindowsMultiWindow (); } static void ClientResize(HWND hWnd, int nWidth, int nHeight) { RECT rcClient, rcWindow; POINT ptDiff; GetClientRect(hWnd, &rcClient); GetWindowRect(hWnd, &rcWindow); ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right; ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom; MoveWindow(hWnd,rcWindow.left, rcWindow.top, nWidth + ptDiff.x, nHeight + ptDiff.y, TRUE); } /* * winCreateWindowsWindow - Create a Windows window associated with an X window */ void winCreateWindowsWindow (WindowPtr pWin) { int iX, iY; int iWidth; int iHeight; HWND hWnd; HWND hFore = NULL; winWindowPriv(pWin); HICON hIcon; HICON hIconSmall; winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv; WinXSizeHints hints; WindowPtr pDaddy; winInitMultiWindowClass(); winDebug ("winCreateWindowsWindow - pWin: %08x\n", pWin); iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN); iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN); iWidth = pWin->drawable.width; iHeight = pWin->drawable.height; /* ensure window actually ends up somewhere visible */ if (iX > GetSystemMetrics (SM_CXVIRTUALSCREEN)) iX = CW_USEDEFAULT; if (iY > GetSystemMetrics (SM_CYVIRTUALSCREEN)) iY = CW_USEDEFAULT; if (winMultiWindowGetTransientFor (pWin, &pDaddy)) { if (pDaddy) { hFore = GetForegroundWindow(); if (hFore && (pDaddy != (WindowPtr)GetProp(hFore, WIN_WID_PROP))) hFore = NULL; } } else { /* Default positions if none specified */ if (!winMultiWindowGetWMNormalHints(pWin, &hints)) hints.flags = 0; if (!(hints.flags & (USPosition|PPosition)) && !pWin->overrideRedirect) { iX = CW_USEDEFAULT; iY = CW_USEDEFAULT; } } /* Create the window */ /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */ /* CW_USEDEFAULT, change back to popup after creation */ hWnd = CreateWindowExA (WS_EX_TOOLWINDOW, /* Extended styles */ WINDOW_CLASS_X, /* Class name */ WINDOW_TITLE_X, /* Window name */ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, iX, /* Horizontal position */ iY, /* Vertical position */ iWidth, /* Right edge */ iHeight, /* Bottom edge */ hFore, /* Null or Parent window if transient*/ (HMENU) NULL, /* No menu */ GetModuleHandle (NULL), /* Instance handle */ pWin); /* ScreenPrivates */ if (hWnd == NULL) { ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", (int) GetLastError ()); } pWinPriv->hWnd = hWnd; /* Set application or .XWinrc defined Icons */ winSelectIcons(pWin, &hIcon, &hIconSmall); if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); if (hIconSmall) SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); /* If we asked the native WM to place the window, synchronize the X window position */ if ((iX == CW_USEDEFAULT) || (iY == CW_USEDEFAULT)) winAdjustXWindow(pWin, hWnd); /* Change style back to popup, already placed... */ SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); SetWindowPos (hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); /* Make sure it gets the proper system menu for a WS_POPUP, too */ GetSystemMenu (hWnd, TRUE); ClientResize(hWnd,iWidth,iHeight); /* Cause any .XWinrc menus to be added in main WNDPROC */ PostMessage (hWnd, WM_INIT_SYS_MENU, 0, 0); SetProp (hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin)); /* Flag that this Windows window handles its own activation */ SetProp (hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0); /* Call engine-specific create window procedure */ (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin); } Bool winInDestroyWindowsWindow = FALSE; /* * winDestroyWindowsWindow - Destroy a Windows window associated * with an X window */ static void winDestroyWindowsWindow (WindowPtr pWin) { MSG msg; winWindowPriv(pWin); BOOL oldstate = winInDestroyWindowsWindow; #if CYGMULTIWINDOW_DEBUG winDebug ("winDestroyWindowsWindow\n"); #endif /* Bail out if the Windows window handle is invalid */ if (pWinPriv->hWnd == NULL) return; winInDestroyWindowsWindow = TRUE; SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, NULL); /* Destroy the Windows window */ DestroyWindow (pWinPriv->hWnd); /* Null our handle to the Window so referencing it will cause an error */ pWinPriv->hWnd = NULL; /* Process all messages on our queue */ while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { if (g_hDlgDepthChange == 0 || !IsDialogMessage (g_hDlgDepthChange, &msg)) { DispatchMessage (&msg); } } winInDestroyWindowsWindow = oldstate; #if CYGMULTIWINDOW_DEBUG winDebug ("-winDestroyWindowsWindow\n"); #endif } /* * winUpdateWindowsWindow - Redisplay/redraw a Windows window * associated with an X window */ static void winUpdateWindowsWindow (WindowPtr pWin) { winWindowPriv(pWin); HWND hWnd = pWinPriv->hWnd; #if CYGMULTIWINDOW_DEBUG winDebug ("winUpdateWindowsWindow\n"); #endif /* Check if the Windows window's parents have been destroyed */ if (pWin->parent != NULL && pWin->parent->parent == NULL && pWin->mapped) { /* Create the Windows window if it has been destroyed */ if (hWnd == NULL) { winCreateWindowsWindow (pWin); assert (pWinPriv->hWnd != NULL); } /* Display the window without activating it */ ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); /* Send first paint message */ UpdateWindow (pWinPriv->hWnd); } else if (hWnd != NULL) { /* Destroy the Windows window if its parents are destroyed */ winDestroyWindowsWindow (pWin); assert (pWinPriv->hWnd == NULL); } #if CYGMULTIWINDOW_DEBUG winDebug ("-winUpdateWindowsWindow\n"); #endif } /* * winGetWindowID - */ XID winGetWindowID (WindowPtr pWin) { WindowIDPairRec wi = {pWin, 0}; ClientPtr c = wClient(pWin); /* */ FindClientResourcesByType (c, RT_WINDOW, winFindWindow, &wi); #if CYGMULTIWINDOW_DEBUG winDebug ("winGetWindowID - Window ID: %d\n", wi.id); #endif return wi.id; } /* * winFindWindow - */ static void winFindWindow (pointer value, XID id, pointer cdata) { WindowIDPairPtr wi = (WindowIDPairPtr)cdata; if (value == wi->value) { wi->id = id; } } /* * winReorderWindowsMultiWindow - */ void winReorderWindowsMultiWindow (void) { HWND hwnd = NULL; WindowPtr pWin = NULL; WindowPtr pWinSib = NULL; XID vlist[2]; static Bool fRestacking = FALSE; /* Avoid recusive calls to this function */ DWORD dwCurrentProcessID = GetCurrentProcessId (); DWORD dwWindowProcessID = 0; winDebug ("winReorderWindowsMultiWindow\n"); if (fRestacking) { /* It is a recusive call so immediately exit */ winDebug ("winReorderWindowsMultiWindow - " "exit because fRestacking == TRUE\n"); return; } fRestacking = TRUE; /* Loop through top level Window windows, descending in Z order */ for ( hwnd = GetTopWindow (NULL); hwnd; hwnd = GetNextWindow (hwnd, GW_HWNDNEXT) ) { /* Don't take care of other Cygwin/X process's windows */ GetWindowThreadProcessId (hwnd, &dwWindowProcessID); if ( GetProp (hwnd, WIN_WINDOW_PROP) && (dwWindowProcessID == dwCurrentProcessID) && !IsIconic (hwnd) ) /* ignore minimized windows */ { pWinSib = pWin; pWin = GetProp (hwnd, WIN_WINDOW_PROP); if (!pWinSib) { /* 1st window - raise to the top */ vlist[0] = Above; ConfigureWindow (pWin, CWStackMode, vlist, wClient(pWin)); } else { /* 2nd or deeper windows - just below the previous one */ vlist[0] = winGetWindowID (pWinSib); vlist[1] = Below; ConfigureWindow (pWin, CWSibling | CWStackMode, vlist, wClient(pWin)); } } } fRestacking = FALSE; } /* * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE */ void winMinimizeWindow (Window id) { WindowPtr pWin; winPrivWinPtr pWinPriv; #ifdef XWIN_MULTIWINDOWEXTWM win32RootlessWindowPtr pRLWinPriv; #endif HWND hWnd; ScreenPtr pScreen = NULL; winPrivScreenPtr pScreenPriv = NULL; winScreenInfo *pScreenInfo = NULL; winDebug ("winMinimizeWindow\n"); dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, DixUnknownAccess); if (!pWin) { ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__); return; } pScreen = pWin->drawable.pScreen; if (pScreen) pScreenPriv = winGetScreenPriv(pScreen); if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo; #ifdef XWIN_MULTIWINDOWEXTWM if (pScreenPriv && pScreenInfo->fInternalWM) { pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE); hWnd = pRLWinPriv->hWnd; } else #else if (pScreenPriv) #endif { pWinPriv = winGetWindowPriv (pWin); hWnd = pWinPriv->hWnd; } ShowWindow (hWnd, SW_MINIMIZE); } /* * CopyWindow - See Porting Layer Definition - p. 39 */ void winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt, RegionPtr oldRegion) { ScreenPtr pScreen = pWin->drawable.pScreen; winScreenPriv(pScreen); winDebug ("CopyWindowMultiWindow\n"); WIN_UNWRAP(CopyWindow); (*pScreen->CopyWindow)(pWin, oldpt, oldRegion); WIN_WRAP(CopyWindow, winCopyWindowMultiWindow); } /* * MoveWindow - See Porting Layer Definition - p. 42 */ void winMoveWindowMultiWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) { ScreenPtr pScreen = pWin->drawable.pScreen; winScreenPriv(pScreen); winDebug ("MoveWindowMultiWindow to (%d, %d)\n", x, y); WIN_UNWRAP(MoveWindow); (*pScreen->MoveWindow)(pWin, x, y, pSib, kind); WIN_WRAP(MoveWindow, winMoveWindowMultiWindow); } /* * ResizeWindow - See Porting Layer Definition - p. 42 */ void winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib) { ScreenPtr pScreen = pWin->drawable.pScreen; winScreenPriv(pScreen); winDebug ("ResizeWindowMultiWindow to (%d, %d) - %dx%d\n", x, y, w, h); WIN_UNWRAP(ResizeWindow); (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); WIN_WRAP(ResizeWindow, winResizeWindowMultiWindow); } /* * winAdjustXWindow * * Move and resize X window with respect to corresponding Windows window. * This is called from WM_MOVE/WM_SIZE handlers when the user performs * any windowing operation (move, resize, minimize, maximize, restore). * * The functionality is the inverse of winPositionWindowMultiWindow, which * adjusts Windows window with respect to X window. */ int winAdjustXWindow (WindowPtr pWin, HWND hwnd) { RECT rcDraw; /* Rect made from pWin->drawable to be adjusted */ RECT rcWin; /* The source: WindowRect from hwnd */ DrawablePtr pDraw; XID vlist[4]; LONG dX, dY, dW, dH, x, y; DWORD dwStyle, dwExStyle; #define WIDTH(rc) (rc.right - rc.left) #define HEIGHT(rc) (rc.bottom - rc.top) winDebug ("winAdjustXWindow\n"); if (IsIconic (hwnd)) { winDebug ("\timmediately return because the window is iconized\n"); /* * If the Windows window is minimized, its WindowRect has * meaningless values so we don't adjust X window to it. */ vlist[0] = 0; vlist[1] = 0; return ConfigureWindow (pWin, CWX | CWY, vlist, wClient(pWin)); } pDraw = &pWin->drawable; /* Calculate the window rect from the drawable */ x = pDraw->x + GetSystemMetrics (SM_XVIRTUALSCREEN); y = pDraw->y + GetSystemMetrics (SM_YVIRTUALSCREEN); SetRect (&rcDraw, x, y, x + pDraw->width, y + pDraw->height); winDebug("\tDrawable extend {%d, %d, %d, %d}, {%d, %d}\n", rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top); dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE); dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE); winDebug("\tWindowStyle: %08x %08x\n", dwStyle, dwExStyle); AdjustWindowRectEx (&rcDraw, dwStyle, FALSE, dwExStyle); /* The source of adjust */ GetWindowRect (hwnd, &rcWin); winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n", rcWin.left, rcWin.top, rcWin.right, rcWin.bottom, rcWin.right - rcWin.left, rcWin.bottom - rcWin.top); winDebug("\tDraw extend {%d, %d, %d, %d}, {%d, %d}\n", rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top); if (EqualRect (&rcDraw, &rcWin)) { /* Bail if no adjust is needed */ winDebug ("\treturn because already adjusted\n"); return 0; } /* Calculate delta values */ dX = rcWin.left - rcDraw.left; dY = rcWin.top - rcDraw.top; dW = WIDTH(rcWin) - WIDTH(rcDraw); dH = HEIGHT(rcWin) - HEIGHT(rcDraw); /* * Adjust. * We may only need to move (vlist[0] and [1]), or only resize * ([2] and [3]) but currently we set all the parameters and leave * the decision to ConfigureWindow. The reason is code simplicity. */ vlist[0] = pDraw->x + dX - wBorderWidth(pWin); vlist[1] = pDraw->y + dY - wBorderWidth(pWin); vlist[2] = pDraw->width + dW; vlist[3] = pDraw->height + dH; winDebug ("\tConfigureWindow to (%ld, %ld) - %ldx%ld\n", vlist[0], vlist[1], vlist[2], vlist[3]); return ConfigureWindow (pWin, CWX | CWY | CWWidth | CWHeight, vlist, wClient(pWin)); #undef WIDTH #undef HEIGHT }