From c862df0add8d4e5ab4770574b45e13016cba6422 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sat, 8 May 2004 12:42:46 +0000 Subject: [PATCH] fixed handling of CW_USEDEFAULT with CreateWindow(Ex)() svn path=/trunk/; revision=9322 --- reactos/lib/user32/windows/window.c | 108 +------------ reactos/subsys/win32k/include/desktop.h | 4 +- reactos/subsys/win32k/include/window.h | 2 + reactos/subsys/win32k/ntuser/desktop.c | 15 +- reactos/subsys/win32k/ntuser/misc.c | 4 +- reactos/subsys/win32k/ntuser/window.c | 195 +++++++++++++++++++++--- reactos/subsys/win32k/ntuser/winpos.c | 8 +- 7 files changed, 194 insertions(+), 142 deletions(-) diff --git a/reactos/lib/user32/windows/window.c b/reactos/lib/user32/windows/window.c index 2e655fc407b..c70a186e369 100644 --- a/reactos/lib/user32/windows/window.c +++ b/reactos/lib/user32/windows/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.115 2004/05/02 17:25:21 weiden Exp $ +/* $Id: window.c,v 1.116 2004/05/08 12:42:45 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -168,7 +168,6 @@ CreateWindowExA(DWORD dwExStyle, UNICODE_STRING ClassName; WNDCLASSEXA wce; HWND Handle; - INT sw; #if 0 DbgPrint("[window] CreateWindowExA style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent); @@ -211,56 +210,6 @@ CreateWindowExA(DWORD dwExStyle, SetLastError(ERROR_OUTOFMEMORY); return (HWND)0; } - - /* Fixup default coordinates. */ - sw = SW_SHOW; - if (x == (LONG) CW_USEDEFAULT || nWidth == (LONG) CW_USEDEFAULT) - { - if (dwStyle & (WS_CHILD | WS_POPUP)) - { - if (x == (LONG) CW_USEDEFAULT) - { - x = y = 0; - } - if (nWidth == (LONG) CW_USEDEFAULT) - { - nWidth = nHeight = 0; - } - } - else - { - STARTUPINFOA info; - - GetStartupInfoA(&info); - - if (x == (LONG) CW_USEDEFAULT) - { - if (y != (LONG) CW_USEDEFAULT) - { - sw = y; - } - x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0; - y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0; - } - - if (nWidth == (LONG) CW_USEDEFAULT) - { - if (info.dwFlags & STARTF_USESIZE) - { - nWidth = info.dwXSize; - nHeight = info.dwYSize; - } - else - { - RECT r; - - SystemParametersInfoA(SPI_GETWORKAREA, 0, &r, 0); - nWidth = (((r.right - r.left) * 3) / 4) - x; - nHeight = (((r.bottom - r.top) * 3) / 4) - y; - } - } - } - } if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP))) { @@ -283,7 +232,7 @@ CreateWindowExA(DWORD dwExStyle, hMenu, hInstance, lpParam, - sw, + SW_SHOW, FALSE); #if 0 @@ -322,7 +271,6 @@ CreateWindowExW(DWORD dwExStyle, UNICODE_STRING ClassName; WNDCLASSEXW wce; HANDLE Handle; - UINT sw; /* Register built-in controls if not already done */ if (! ControlsInitialized) @@ -346,56 +294,6 @@ CreateWindowExW(DWORD dwExStyle, RtlInitUnicodeString(&WindowName, lpWindowName); - /* Fixup default coordinates. */ - sw = SW_SHOW; - if (x == (LONG) CW_USEDEFAULT || nWidth == (LONG) CW_USEDEFAULT) - { - if (dwStyle & (WS_CHILD | WS_POPUP)) - { - if (x == (LONG) CW_USEDEFAULT) - { - x = y = 0; - } - if (nWidth == (LONG) CW_USEDEFAULT) - { - nWidth = nHeight = 0; - } - } - else - { - STARTUPINFOW info; - - GetStartupInfoW(&info); - - if (x == (LONG) CW_USEDEFAULT) - { - if (y != (LONG) CW_USEDEFAULT) - { - sw = y; - } - x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0; - y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0; - } - - if (nWidth == (LONG) CW_USEDEFAULT) - { - if (info.dwFlags & STARTF_USESIZE) - { - nWidth = info.dwXSize; - nHeight = info.dwYSize; - } - else - { - RECT r; - - SystemParametersInfoW(SPI_GETWORKAREA, 0, &r, 0); - nWidth = (((r.right - r.left) * 3) / 4) - x; - nHeight = (((r.bottom - r.top) * 3) / 4) - y; - } - } - } - } - if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP))) { wce.cbSize = sizeof(WNDCLASSEXW); @@ -417,7 +315,7 @@ CreateWindowExW(DWORD dwExStyle, hMenu, hInstance, lpParam, - sw, + SW_SHOW, TRUE); return (HWND)Handle; diff --git a/reactos/subsys/win32k/include/desktop.h b/reactos/subsys/win32k/include/desktop.h index 40cf4d86ca0..2c49a77caba 100644 --- a/reactos/subsys/win32k/include/desktop.h +++ b/reactos/subsys/win32k/include/desktop.h @@ -19,8 +19,8 @@ InitDesktopImpl(VOID); NTSTATUS FASTCALL CleanupDesktopImpl(VOID); -PRECT FASTCALL -IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop); +VOID FASTCALL +IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect); LRESULT CALLBACK IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); diff --git a/reactos/subsys/win32k/include/window.h b/reactos/subsys/win32k/include/window.h index bf218effd2c..77a280a0b63 100644 --- a/reactos/subsys/win32k/include/window.h +++ b/reactos/subsys/win32k/include/window.h @@ -95,6 +95,8 @@ typedef struct _WINDOW_OBJECT HWND hWndLastPopup; /* handle to last active popup window (wine doesn't use pointer, for unk. reason)*/ PINTERNALPOS InternalPos; ULONG Status; + /* counter for tiled child windows */ + ULONG TiledCounter; } WINDOW_OBJECT; /* PWINDOW_OBJECT already declared at top of file */ /* Window flags. */ diff --git a/reactos/subsys/win32k/ntuser/desktop.c b/reactos/subsys/win32k/ntuser/desktop.c index 75f124315a0..a59d3836ffb 100644 --- a/reactos/subsys/win32k/ntuser/desktop.c +++ b/reactos/subsys/win32k/ntuser/desktop.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: desktop.c,v 1.12 2004/05/05 22:47:06 weiden Exp $ + * $Id: desktop.c,v 1.13 2004/05/08 12:42:46 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -118,11 +118,13 @@ IntValidateDesktopHandle( return Status; } -PRECT FASTCALL -IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop) +VOID FASTCALL +IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect) { PRECT Ret; + ASSERT(Desktop); + Ret = &Desktop->WorkArea; if((Ret->right == -1) && ScreenDeviceContext) { @@ -138,7 +140,10 @@ IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop) DC_UnlockDc(ScreenDeviceContext); } - return Ret; + if(Rect) + { + *Rect = *Ret; + } } PDESKTOP_OBJECT FASTCALL @@ -432,7 +437,7 @@ NtUserCreateDesktop( DesktopObject->WorkArea.top = 0; DesktopObject->WorkArea.right = -1; DesktopObject->WorkArea.bottom = -1; - IntGetDesktopWorkArea(DesktopObject); + IntGetDesktopWorkArea(DesktopObject, NULL); /* Initialize some local (to win32k) desktop state. */ DesktopObject->ActiveMessageQueue = NULL; diff --git a/reactos/subsys/win32k/ntuser/misc.c b/reactos/subsys/win32k/ntuser/misc.c index c2195ccd5b4..cf64bbda9d7 100644 --- a/reactos/subsys/win32k/ntuser/misc.c +++ b/reactos/subsys/win32k/ntuser/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.69 2004/05/02 17:25:21 weiden Exp $ +/* $Id: misc.c,v 1.70 2004/05/08 12:42:46 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -711,7 +711,7 @@ IntSystemParametersInfo( } ASSERT(pvParam); - *((PRECT)pvParam) = *(IntGetDesktopWorkArea(Desktop)); + IntGetDesktopWorkArea(Desktop, (PRECT)pvParam); return TRUE; } diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 5d4b289cec9..963e2ee9da7 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: window.c,v 1.224 2004/05/05 22:26:04 weiden Exp $ +/* $Id: window.c,v 1.225 2004/05/08 12:42:46 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -64,6 +64,9 @@ static WndProcHandle *WndProcHandlesArray = 0; static WORD WndProcHandlesArraySize = 0; #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */ +/* dialog resources appear to pass this in 16 bits, handle them properly */ +#define CW_USEDEFAULT16 (0x8000) + #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x ))) /* PRIVATE FUNCTIONS **********************************************************/ @@ -1354,6 +1357,57 @@ NtUserChildWindowFromPointEx(HWND hwndParent, } +/* + * calculates the default position of a window + */ +BOOL FASTCALL +IntCalcDefPosSize(PWINDOW_OBJECT Parent, PWINDOW_OBJECT WindowObject, RECT *rc, BOOL IncPos) +{ + PDESKTOP_OBJECT Desktop; + SIZE Sz; + POINT Pos; + DbgPrint("IntCalcDefPosSize: Parent: 0x%x, Window: 0x%x, IncPos: 0x%x\n", Parent, WindowObject, IncPos); + Desktop = WindowObject->OwnerThread->Win32Thread->Desktop; + IntGetDesktopWorkArea(Desktop, rc); + + if(Parent != NULL) + { + NtGdiIntersectRect(rc, rc, &Parent->ClientRect); + + if(IncPos) + { + Pos.x = Parent->TiledCounter * (NtUserGetSystemMetrics(SM_CXSIZE) + NtUserGetSystemMetrics(SM_CXFRAME)); + Pos.y = Parent->TiledCounter * (NtUserGetSystemMetrics(SM_CYSIZE) + NtUserGetSystemMetrics(SM_CYFRAME)); + if(Pos.x > ((rc->right - rc->left) / 4) || + Pos.y > ((rc->bottom - rc->top) / 4)) + { + /* reset counter and position */ + Pos.x = 0; + Pos.y = 0; + Parent->TiledCounter = 0; + } + Parent->TiledCounter++; + } + Pos.x += rc->left; + Pos.y += rc->top; + } + else + { + Pos.x = rc->left; + Pos.y = rc->top; + } + + Sz.cx = EngMulDiv(rc->right - rc->left, 3, 4); + Sz.cy = EngMulDiv(rc->bottom - rc->top, 3, 4); + + rc->left = Pos.x; + rc->top = Pos.y; + rc->right = rc->left + Sz.cx; + rc->bottom = rc->top + Sz.cy; + return TRUE; +} + + /* * @implemented */ @@ -1383,6 +1437,8 @@ NtUserCreateWindowEx(DWORD dwExStyle, UNICODE_STRING WindowName; NTSTATUS Status; HANDLE Handle; + POINT Pos; + SIZE Size; #if 0 POINT MaxSize, MaxPos, MinTrack, MaxTrack; #else @@ -1607,6 +1663,13 @@ NtUserCreateWindowEx(DWORD dwExStyle, } } + if(!(WindowObject->Style & (WS_POPUP | WS_CHILD))) + { + /* Automatically assign the caption and border style. Also always + clip siblings for overlapped windows. */ + WindowObject->Style |= (WS_CAPTION | WS_BORDER | WS_CLIPSIBLINGS); + } + /* create system menu */ if((WindowObject->Style & WS_SYSMENU) && (WindowObject->Style & WS_CAPTION)) { @@ -1631,26 +1694,20 @@ NtUserCreateWindowEx(DWORD dwExStyle, } /* FIXME: Handle "CS_CLASSDC" */ - /* Initialize the window dimensions. */ - WindowObject->WindowRect.left = x; - WindowObject->WindowRect.top = y; - WindowObject->WindowRect.right = x + nWidth; - WindowObject->WindowRect.bottom = y + nHeight; - if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow) - { - NtGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left, - ParentWindow->ClientRect.top); - } - WindowObject->ClientRect = WindowObject->WindowRect; + Pos.x = x; + Pos.y = y; + Size.cx = nWidth; + Size.cy = nHeight; + /* call hook */ Cs.lpCreateParams = lpParam; Cs.hInstance = hInstance; Cs.hMenu = hMenu; Cs.hwndParent = ParentWindowHandle; - Cs.cx = nWidth; - Cs.cy = nHeight; - Cs.x = x; - Cs.y = y; + Cs.cx = Size.cx; + Cs.cy = Size.cy; + Cs.x = Pos.x; + Cs.y = Pos.y; Cs.style = dwStyle; Cs.lpszName = OrigWindowName; /* pass the original pointer to usermode! */ Cs.lpszClass = lpClassName->Buffer; @@ -1667,6 +1724,96 @@ NtUserCreateWindowEx(DWORD dwExStyle, return (HWND) NULL; } + x = Cs.x; + y = Cs.y; + nWidth = Cs.cx; + nHeight = Cs.cy; + + /* default positioning for overlapped windows */ + if(!(WindowObject->Style & (WS_POPUP | WS_CHILD))) + { + RECT rc; + PRTL_USER_PROCESS_PARAMETERS ProcessParams; + BOOL CalculatedDefPosSize = FALSE; + + ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters; + + DbgPrint("Creating WS_OVERLAPPED window (0x%x, 0x%x, 0x%x, 0x%x)\n", x, y, nWidth, nHeight); + if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16) + { + CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow, WindowObject, &rc, TRUE); + + if(ProcessParams->dwFlags & STARTF_USEPOSITION) + { + ProcessParams->dwFlags &= ~STARTF_USEPOSITION; + Pos.x = ProcessParams->dwX; + Pos.y = ProcessParams->dwY; + } + else + { + Pos.x = rc.left; + Pos.y = rc.top; + } + + /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and + y is something else */ + if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16) + { + dwShowMode = y; + } + } + if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16) + { + if(!CalculatedDefPosSize) + { + IntCalcDefPosSize(ParentWindow, WindowObject, &rc, FALSE); + } + if(ProcessParams->dwFlags & STARTF_USESIZE) + { + ProcessParams->dwFlags &= ~STARTF_USESIZE; + Size.cx = ProcessParams->dwXSize; + Size.cy = ProcessParams->dwYSize; + } + else + { + Size.cx = rc.right - rc.left; + Size.cy = rc.bottom - rc.top; + } + + /* move the window if necessary */ + if(Pos.x > rc.left) + Pos.x = max(rc.left, 0); + if(Pos.y > rc.top) + Pos.y = max(rc.top, 0); + } + } + else + { + /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */ + if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16) + { + Pos.x = 0; + Pos.y = 0; + } + if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16) + { + Size.cx = 0; + Size.cy = 0; + } + } + + /* Initialize the window dimensions. */ + WindowObject->WindowRect.left = Pos.x; + WindowObject->WindowRect.top = Pos.y; + WindowObject->WindowRect.right = Pos.x + Size.cx; + WindowObject->WindowRect.bottom = Pos.y + Size.cy; + if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow) + { + NtGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left, + ParentWindow->ClientRect.top); + } + WindowObject->ClientRect = WindowObject->WindowRect; + /* * Get the size and position of the window. */ @@ -1685,10 +1832,10 @@ NtUserCreateWindowEx(DWORD dwExStyle, if (nHeight < 0) nHeight = 0; } - WindowObject->WindowRect.left = x; - WindowObject->WindowRect.top = y; - WindowObject->WindowRect.right = x + nWidth; - WindowObject->WindowRect.bottom = y + nHeight; + WindowObject->WindowRect.left = Pos.x; + WindowObject->WindowRect.top = Pos.y; + WindowObject->WindowRect.right = Pos.x + Size.cx; + WindowObject->WindowRect.bottom = Pos.y + Size.cy; if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow) { NtGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left, @@ -1699,10 +1846,10 @@ NtUserCreateWindowEx(DWORD dwExStyle, /* FIXME: Initialize the window menu. */ /* Send a NCCREATE message. */ - Cs.cx = nWidth; - Cs.cy = nHeight; - Cs.x = x; - Cs.y = y; + Cs.cx = Size.cx; + Cs.cy = Size.cy; + Cs.x = Pos.x; + Cs.y = Pos.y; DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent); DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight); diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c index 02289d787bb..71aa78ab9d1 100644 --- a/reactos/subsys/win32k/ntuser/winpos.c +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: winpos.c,v 1.112 2004/04/24 14:21:36 weiden Exp $ +/* $Id: winpos.c,v 1.113 2004/05/08 12:42:46 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -198,13 +198,13 @@ WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT *pt, PRECT RestoreRect) if(Parent) { if(IntIsDesktopWindow(Parent)) - WorkArea = *IntGetDesktopWorkArea(Desktop); + IntGetDesktopWorkArea(Desktop, &WorkArea); else WorkArea = Parent->ClientRect; IntReleaseWindowObject(Parent); } else - WorkArea = *IntGetDesktopWorkArea(Desktop); + IntGetDesktopWorkArea(Desktop, &WorkArea); WindowObject->InternalPos = ExAllocatePoolWithTag(NonPagedPool, sizeof(INTERNALPOS), TAG_WININTLIST); if(!WindowObject->InternalPos) @@ -347,7 +347,7 @@ WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window, MINMAXINFO *Info) RECT WorkArea; PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop; /* Or rather get it from the window? */ - WorkArea = *IntGetDesktopWorkArea(Desktop); + IntGetDesktopWorkArea(Desktop, &WorkArea); /* Get default values. */ Info->ptMaxSize.x = WorkArea.right - WorkArea.left;