summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon TURNEY <jon.turney@dronecode.org.uk>2010-08-12 15:00:01 +0100
committerJon TURNEY <jon.turney@dronecode.org.uk>2011-06-29 19:14:35 +0100
commite78628406f0428454983db1c51a8c828bf5684e5 (patch)
treed694d7bd9118f5e46de6478a0d9069d795857948
parent1d7f3a0031b4ae7d8aa984799ffa578788061ce4 (diff)
Cygwin/X: Preserve client area size and position on Windows window style change
When the style changes, adjust the window size so the client area remains the same. Otherwise the window size may change when sizing is reflected from Windows to X, and some windows are drawn expecting them to be exactly the requested size (e.g. the gmplayer control window) Use DeferWindowPos to delay the resize to preserve client area on WM_STYLECHANGING until after the style change has actually happened in WM_STYLECHANGED As a consquence of this, we need to be more careful to create windows with exactly the requested placement and client area initially, so the client area matches what the X client requested Also synchronize the X windows idea of the placement of a window which Windows is allowed to place Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk> Reviewed-by: Colin Harrison <colin.harrison@virgin.net> Tested-by: Colin Harrison <colin.harrison@virgin.net>
-rw-r--r--hw/xwin/winmultiwindowwindow.c37
-rw-r--r--hw/xwin/winmultiwindowwndproc.c58
-rw-r--r--hw/xwin/winwindow.h1
3 files changed, 91 insertions, 5 deletions
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;