diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 21b818b89..2d9a46e40 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -493,6 +493,8 @@ winCreateWindowsWindow (WindowPtr pWin) winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv; WinXSizeHints hints; WindowPtr pDaddy; + DWORD dwStyle, dwExStyle; + RECT rc; winInitMultiWindowClass(); @@ -517,6 +519,8 @@ winCreateWindowsWindow (WindowPtr pWin) iY = CW_USEDEFAULT; } + winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + if (winMultiWindowGetTransientFor (pWin, &pDaddy)) { if (pDaddy) @@ -538,16 +542,35 @@ winCreateWindowsWindow (WindowPtr pWin) } } - /* Create the window */ - /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */ + /* Make it WS_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 */ + dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + dwExStyle = WS_EX_TOOLWINDOW; + + /* + Calculate the window coordinates containing the requested client area, + being careful to preseve CW_USEDEFAULT + */ + rc.top = (iY != CW_USEDEFAULT) ? iY : 0; + rc.left = (iX != CW_USEDEFAULT) ? iX : 0; + rc.bottom = rc.top + iHeight; + rc.right = rc.left + iWidth; + AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); + if (iY != CW_USEDEFAULT) iY = rc.top; + if (iX != CW_USEDEFAULT) iX = rc.left; + iHeight = rc.bottom - rc.top; + iWidth = rc.right - rc.left; + + winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + + /* Create the window */ + hWnd = CreateWindowExA (dwExStyle, /* Extended styles */ WINDOW_CLASS_X, /* Class name */ WINDOW_TITLE_X, /* Window name */ - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + dwStyle, /* Styles */ iX, /* Horizontal position */ iY, /* Vertical position */ - iWidth, /* Right edge */ + iWidth, /* Right edge */ iHeight, /* Bottom edge */ hFore, /* Null or Parent window if transient*/ (HMENU) NULL, /* No menu */ @@ -569,6 +592,10 @@ winCreateWindowsWindow (WindowPtr pWin) 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); + + /* Adjust the X window to match the window placement we actually got... */ + winAdjustXWindow (pWin, hWnd); + /* Make sure it gets the proper system menu for a WS_POPUP, too */ GetSystemMenu (hWnd, TRUE); diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index b559cd8cf..1a3be78d5 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -1008,6 +1008,64 @@ winTopLevelWindowProc (HWND hwnd, UINT message, winAdjustXWindow (pWin, hwnd); return 0; /* end of WM_SIZE handler */ + case WM_STYLECHANGING: + /* + When the style changes, adjust the Windows window size so the client area remains the same size, + and adjust the Windows window position so that the client area remains in the same place. + */ + { + RECT newWinRect; + DWORD dwExStyle; + DWORD dwStyle; + DWORD newStyle = ((STYLESTRUCT *)lParam)->styleNew; + WINDOWINFO wi; + + dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE); + dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE); + + winDebug("winTopLevelWindowProc - WM_STYLECHANGING from %08x %08x\n", dwStyle, dwExStyle); + + if (wParam == GWL_EXSTYLE) + dwExStyle = newStyle; + + if (wParam == GWL_STYLE) + dwStyle = newStyle; + + winDebug("winTopLevelWindowProc - WM_STYLECHANGING to %08x %08x\n", dwStyle, dwExStyle); + + /* Get client rect in screen coordinates */ + wi.cbSize = sizeof(WINDOWINFO); + GetWindowInfo(hwnd, &wi); + + winDebug("winTopLevelWindowProc - WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n", wi.rcClient.left, wi.rcClient.top, wi.rcClient.right, wi.rcClient.bottom, wi.rcClient.right - wi.rcClient.left, wi.rcClient.bottom - wi.rcClient.top); + + newWinRect = wi.rcClient; + if (!AdjustWindowRectEx(&newWinRect, dwStyle, FALSE, dwExStyle)) + winDebug("winTopLevelWindowProc - WM_STYLECHANGING AdjustWindowRectEx failed\n"); + + winDebug("winTopLevelWindowProc - WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n", newWinRect.left, newWinRect.top, newWinRect.right, newWinRect.bottom, newWinRect.right - newWinRect.left, newWinRect.bottom - newWinRect.top); + + /* + Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow() + which WM_SIZE does will use the current (unchanged) style. Instead make a note to change it when + WM_STYLECHANGED is received... + */ + pWinPriv->hDwp = BeginDeferWindowPos(1); + pWinPriv->hDwp = DeferWindowPos(pWinPriv->hDwp, hwnd, NULL, newWinRect.left, newWinRect.top, newWinRect.right - newWinRect.left, newWinRect.bottom - newWinRect.top, SWP_NOACTIVATE | SWP_NOZORDER); + } + return 0; + + case WM_STYLECHANGED: + { + if (pWinPriv->hDwp) + { + EndDeferWindowPos(pWinPriv->hDwp); + pWinPriv->hDwp = NULL; + } + winDebug("winTopLevelWindowProc - WM_STYLECHANGED done\n"); + } + return 0; + case WM_MOUSEACTIVATE: /* Check if this window needs to be made active when clicked */ diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index cf2f93f0a..ebe43091f 100644 --- a/hw/xwin/winwindow.h +++ b/hw/xwin/winwindow.h @@ -79,6 +79,7 @@ typedef struct HWND hWnd; winPrivScreenPtr pScreenPriv; Bool fXKilled; + HDWP hDwp; /* Privates used by primary fb DirectDraw server */ LPDDSURFACEDESC pddsdPrimary;