From 936ab3a64441656daa1320825d0eb4e89c4f59e6 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 28 Feb 2008 16:09:39 +0100 Subject: [PATCH] user32: Moved the ShowWindow implementation from winex11 back to user32. --- dlls/user32/driver.c | 13 -- dlls/user32/user32.spec | 1 - dlls/user32/user_private.h | 1 - dlls/user32/win.c | 20 +- dlls/user32/winpos.c | 321 +++++++++++++++++++++++++++++- dlls/winex11.drv/window.c | 21 -- dlls/winex11.drv/winex11.drv.spec | 1 - dlls/winex11.drv/winpos.c | 314 ----------------------------- include/win.h | 4 +- 9 files changed, 339 insertions(+), 357 deletions(-) diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index d5f1fa08222..d773c0801f6 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -119,7 +119,6 @@ static const USER_DRIVER *load_driver(void) GET_USER_FUNC(SetWindowIcon); GET_USER_FUNC(SetWindowStyle); GET_USER_FUNC(SetWindowText); - GET_USER_FUNC(ShowWindow); GET_USER_FUNC(SysCommandSizeMove); GET_USER_FUNC(WindowMessage); #undef GET_USER_FUNC @@ -396,11 +395,6 @@ static void nulldrv_SetWindowText( HWND hwnd, LPCWSTR text ) { } -static BOOL nulldrv_ShowWindow( HWND hwnd, INT cmd ) -{ - return FALSE; -} - static void nulldrv_SysCommandSizeMove( HWND hwnd, WPARAM wparam ) { } @@ -465,7 +459,6 @@ static const USER_DRIVER null_driver = nulldrv_SetWindowIcon, nulldrv_SetWindowStyle, nulldrv_SetWindowText, - nulldrv_ShowWindow, nulldrv_SysCommandSizeMove, nulldrv_WindowMessage }; @@ -721,11 +714,6 @@ static void loaderdrv_SetWindowText( HWND hwnd, LPCWSTR text ) load_driver()->pSetWindowText( hwnd, text ); } -static BOOL loaderdrv_ShowWindow( HWND hwnd, INT cmd ) -{ - return load_driver()->pShowWindow( hwnd, cmd ); -} - static void loaderdrv_SysCommandSizeMove( HWND hwnd, WPARAM wparam ) { load_driver()->pSysCommandSizeMove( hwnd, wparam ); @@ -791,7 +779,6 @@ static const USER_DRIVER lazy_load_driver = loaderdrv_SetWindowIcon, loaderdrv_SetWindowStyle, loaderdrv_SetWindowText, - loaderdrv_ShowWindow, loaderdrv_SysCommandSizeMove, loaderdrv_WindowMessage }; diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 6b7e0853b07..0f72fa1ded5 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -789,7 +789,6 @@ # @ cdecl HOOK_CallHooks(long long long long long) @ cdecl USER_Unlock() -@ cdecl WINPOS_ActivateOtherWindow(long) @ cdecl WINPOS_GetMinMaxInfo(long ptr ptr ptr ptr) @ cdecl WINPOS_ShowIconTitle(long long) @ cdecl WIN_GetPtr(long) diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 0b5efe28634..82921587b82 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -155,7 +155,6 @@ typedef struct tagUSER_DRIVER { void (*pSetWindowIcon)(HWND,UINT,HICON); void (*pSetWindowStyle)(HWND,DWORD); void (*pSetWindowText)(HWND,LPCWSTR); - BOOL (*pShowWindow)(HWND,INT); void (*pSysCommandSizeMove)(HWND,WPARAM); LRESULT (*pWindowMessage)(HWND,UINT,WPARAM,LPARAM); } USER_DRIVER; diff --git a/dlls/user32/win.c b/dlls/user32/win.c index bdce3343429..76351f46232 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -868,7 +868,7 @@ static void dump_window_styles( DWORD style, DWORD exstyle ) */ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags ) { - INT cx, cy, sw = SW_SHOW; + INT cx, cy, style, sw = SW_SHOW; LRESULT result; RECT rect; WND *wndPtr; @@ -1153,6 +1153,10 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ); if (result == -1) goto failed; + /* call the driver */ + + if (!USER_Driver->pCreateWindow( hwnd )) goto failed; + NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0); /* send the size messages */ @@ -1168,9 +1172,19 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags } else WIN_ReleasePtr( wndPtr ); - /* call the driver */ + /* Show the window, maximizing or minimizing if needed */ - if (!USER_Driver->pCreateWindow( hwnd )) goto failed; + style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE ); + if (style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + RECT newPos; + UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE; + + swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos ); + swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */ + if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE; + SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag ); + } /* Notify the parent window only */ diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 451dd3b5795..cc6309ade0e 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -859,6 +859,323 @@ void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos, if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize; } + +/*********************************************************************** + * WINPOS_FindIconPos + * + * Find a suitable place for an iconic window. + */ +static POINT WINPOS_FindIconPos( HWND hwnd, POINT pt ) +{ + RECT rect, rectParent; + HWND parent, child; + HRGN hrgn, tmp; + int xspacing, yspacing; + + parent = GetAncestor( hwnd, GA_PARENT ); + GetClientRect( parent, &rectParent ); + if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) && + (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom)) + return pt; /* The icon already has a suitable position */ + + xspacing = GetSystemMetrics(SM_CXICONSPACING); + yspacing = GetSystemMetrics(SM_CYICONSPACING); + + /* Check if another icon already occupies this spot */ + /* FIXME: this is completely inefficient */ + + hrgn = CreateRectRgn( 0, 0, 0, 0 ); + tmp = CreateRectRgn( 0, 0, 0, 0 ); + for (child = GetWindow( parent, GW_HWNDFIRST ); child; child = GetWindow( child, GW_HWNDNEXT )) + { + WND *childPtr; + if (child == hwnd) continue; + if ((GetWindowLongW( child, GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE)) + continue; + if (!(childPtr = WIN_GetPtr( child )) || childPtr == WND_OTHER_PROCESS) + continue; + SetRectRgn( tmp, childPtr->rectWindow.left, childPtr->rectWindow.top, + childPtr->rectWindow.right, childPtr->rectWindow.bottom ); + CombineRgn( hrgn, hrgn, tmp, RGN_OR ); + WIN_ReleasePtr( childPtr ); + } + DeleteObject( tmp ); + + for (rect.bottom = rectParent.bottom; rect.bottom >= yspacing; rect.bottom -= yspacing) + { + for (rect.left = rectParent.left; rect.left <= rectParent.right - xspacing; rect.left += xspacing) + { + rect.right = rect.left + xspacing; + rect.top = rect.bottom - yspacing; + if (!RectInRegion( hrgn, &rect )) + { + /* No window was found, so it's OK for us */ + pt.x = rect.left + (xspacing - GetSystemMetrics(SM_CXICON)) / 2; + pt.y = rect.top + (yspacing - GetSystemMetrics(SM_CYICON)) / 2; + DeleteObject( hrgn ); + return pt; + } + } + } + DeleteObject( hrgn ); + pt.x = pt.y = 0; + return pt; +} + + +/*********************************************************************** + * WINPOS_MinMaximize + */ +UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) +{ + WND *wndPtr; + UINT swpFlags = 0; + POINT size; + LONG old_style; + WINDOWPLACEMENT wpl; + + TRACE("%p %u\n", hwnd, cmd ); + + wpl.length = sizeof(wpl); + GetWindowPlacement( hwnd, &wpl ); + + if (HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE )) + return SWP_NOSIZE | SWP_NOMOVE; + + if (IsIconic( hwnd )) + { + switch (cmd) + { + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: + case SW_MINIMIZE: + return SWP_NOSIZE | SWP_NOMOVE; + } + if (!SendMessageW( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE; + swpFlags |= SWP_NOCOPYBITS; + } + + switch( cmd ) + { + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: + case SW_MINIMIZE: + if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; + if( wndPtr->dwStyle & WS_MAXIMIZE) wndPtr->flags |= WIN_RESTORE_MAX; + else wndPtr->flags &= ~WIN_RESTORE_MAX; + WIN_ReleasePtr( wndPtr ); + + old_style = WIN_SetStyle( hwnd, WS_MINIMIZE, WS_MAXIMIZE ); + + wpl.ptMinPosition = WINPOS_FindIconPos( hwnd, wpl.ptMinPosition ); + + if (!(old_style & WS_MINIMIZE)) swpFlags |= SWP_STATECHANGED; + SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) ); + swpFlags |= SWP_NOCOPYBITS; + break; + + case SW_MAXIMIZE: + old_style = GetWindowLongW( hwnd, GWL_STYLE ); + if ((old_style & WS_MAXIMIZE) && (old_style & WS_VISIBLE)) return SWP_NOSIZE | SWP_NOMOVE; + + WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL ); + + old_style = WIN_SetStyle( hwnd, WS_MAXIMIZE, WS_MINIMIZE ); + if (old_style & WS_MINIMIZE) WINPOS_ShowIconTitle( hwnd, FALSE ); + + if (!(old_style & WS_MAXIMIZE)) swpFlags |= SWP_STATECHANGED; + SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); + break; + + case SW_SHOWNOACTIVATE: + case SW_SHOWNORMAL: + case SW_RESTORE: + old_style = WIN_SetStyle( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); + if (old_style & WS_MINIMIZE) + { + BOOL restore_max; + + WINPOS_ShowIconTitle( hwnd, FALSE ); + + if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; + restore_max = (wndPtr->flags & WIN_RESTORE_MAX) != 0; + WIN_ReleasePtr( wndPtr ); + if (restore_max) + { + /* Restore to maximized position */ + WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL); + WIN_SetStyle( hwnd, WS_MAXIMIZE, 0 ); + swpFlags |= SWP_STATECHANGED; + SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); + break; + } + } + else if (!(old_style & WS_MAXIMIZE)) break; + + swpFlags |= SWP_STATECHANGED; + + /* Restore to normal position */ + + *rect = wpl.rcNormalPosition; + rect->right -= rect->left; + rect->bottom -= rect->top; + + break; + } + + return swpFlags; +} + + +/*********************************************************************** + * show_window + * + * Implementation of ShowWindow and ShowWindowAsync. + */ +static BOOL show_window( HWND hwnd, INT cmd ) +{ + WND *wndPtr; + HWND parent; + LONG style = GetWindowLongW( hwnd, GWL_STYLE ); + BOOL wasVisible = (style & WS_VISIBLE) != 0; + BOOL showFlag = TRUE; + RECT newPos = {0, 0, 0, 0}; + UINT swp = 0; + + TRACE("hwnd=%p, cmd=%d, wasVisible %d\n", hwnd, cmd, wasVisible); + + switch(cmd) + { + case SW_HIDE: + if (!wasVisible) return FALSE; + showFlag = FALSE; + swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; + if (hwnd != GetActiveWindow()) + swp |= SWP_NOACTIVATE | SWP_NOZORDER; + break; + + case SW_SHOWMINNOACTIVE: + swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* fall through */ + case SW_MINIMIZE: + case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ + if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* fall through */ + case SW_SHOWMINIMIZED: + swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; + swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos ); + if ((style & WS_MINIMIZE) && wasVisible) return TRUE; + break; + + case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */ + if (!wasVisible) swp |= SWP_SHOWWINDOW; + swp |= SWP_FRAMECHANGED; + swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos ); + if ((style & WS_MAXIMIZE) && wasVisible) return TRUE; + break; + + case SW_SHOWNA: + swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + if (style & WS_CHILD) swp |= SWP_NOZORDER; + break; + case SW_SHOW: + if (wasVisible) return TRUE; + swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER; + break; + + case SW_SHOWNOACTIVATE: + swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* fall through */ + case SW_RESTORE: + /* fall through */ + case SW_SHOWNORMAL: /* same as SW_NORMAL: */ + case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ + if (!wasVisible) swp |= SWP_SHOWWINDOW; + if (style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + swp |= SWP_FRAMECHANGED; + swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos ); + } + else + { + if (wasVisible) return TRUE; + swp |= SWP_NOSIZE | SWP_NOMOVE; + } + if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER; + break; + } + + if ((showFlag != wasVisible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED)) + { + SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 ); + if (!IsWindow( hwnd )) return wasVisible; + } + + parent = GetAncestor( hwnd, GA_PARENT ); + if (parent && !IsWindowVisible( parent ) && !(swp & SWP_STATECHANGED)) + { + /* if parent is not visible simply toggle WS_VISIBLE and return */ + if (showFlag) WIN_SetStyle( hwnd, WS_VISIBLE, 0 ); + else WIN_SetStyle( hwnd, 0, WS_VISIBLE ); + } + else + SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, + newPos.right, newPos.bottom, LOWORD(swp) ); + + if (cmd == SW_HIDE) + { + HWND hFocus; + + /* FIXME: This will cause the window to be activated irrespective + * of whether it is owned by the same thread. Has to be done + * asynchronously. + */ + + if (hwnd == GetActiveWindow()) + WINPOS_ActivateOtherWindow(hwnd); + + /* Revert focus to parent */ + hFocus = GetFocus(); + if (hwnd == hFocus || IsChild(hwnd, hFocus)) + { + HWND parent = GetAncestor(hwnd, GA_PARENT); + if (parent == GetDesktopWindow()) parent = 0; + SetFocus(parent); + } + } + + if (IsIconic(hwnd)) WINPOS_ShowIconTitle( hwnd, TRUE ); + + if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return wasVisible; + + if (wndPtr->flags & WIN_NEED_SIZE) + { + /* should happen only in CreateWindowEx() */ + int wParam = SIZE_RESTORED; + RECT client = wndPtr->rectClient; + + wndPtr->flags &= ~WIN_NEED_SIZE; + if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED; + else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED; + WIN_ReleasePtr( wndPtr ); + + SendMessageW( hwnd, WM_SIZE, wParam, + MAKELONG( client.right - client.left, client.bottom - client.top )); + SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top )); + } + else WIN_ReleasePtr( wndPtr ); + + /* if previous state was minimized Windows sets focus to the window */ + if (style & WS_MINIMIZE) SetFocus( hwnd ); + + return wasVisible; +} + + /*********************************************************************** * ShowWindowAsync (USER32.@) * @@ -876,7 +1193,7 @@ BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd ) } if ((full_handle = WIN_IsCurrentThread( hwnd ))) - return USER_Driver->pShowWindow( full_handle, cmd ); + return show_window( full_handle, cmd ); return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); } @@ -895,7 +1212,7 @@ BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) return FALSE; } if ((full_handle = WIN_IsCurrentThread( hwnd ))) - return USER_Driver->pShowWindow( full_handle, cmd ); + return show_window( full_handle, cmd ); return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 2b04ec0aa73..2f6e8a1ad87 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1376,33 +1376,12 @@ BOOL X11DRV_CreateDesktopWindow( HWND hwnd ) BOOL X11DRV_CreateWindow( HWND hwnd ) { Display *display = thread_display(); - DWORD style; if (hwnd == GetDesktopWindow() && root_window != DefaultRootWindow( display )) { /* the desktop win data can't be created lazily */ if (!create_desktop_win_data( display, hwnd )) return FALSE; } - - /* Show the window, maximizing or minimizing if needed */ - - style = GetWindowLongW( hwnd, GWL_STYLE ); - if (style & (WS_MINIMIZE | WS_MAXIMIZE)) - { - extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ); /*FIXME*/ - - RECT newPos; - UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE; - WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE ); - swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos ); - - swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */ - if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE; - - SetWindowPos( hwnd, 0, newPos.left, newPos.top, - newPos.right, newPos.bottom, swFlag ); - } - return TRUE; } diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 74ddb660b76..6c8fe6c08c5 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -110,7 +110,6 @@ @ cdecl SetWindowRgn(long long long) X11DRV_SetWindowRgn @ cdecl SetWindowStyle(ptr long) X11DRV_SetWindowStyle @ cdecl SetWindowText(long wstr) X11DRV_SetWindowText -@ cdecl ShowWindow(long long) X11DRV_ShowWindow @ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove @ cdecl WindowMessage(long long long long) X11DRV_WindowMessage diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c index 7c28a8d2512..4f3c3ad9d8d 100644 --- a/dlls/winex11.drv/winpos.c +++ b/dlls/winex11.drv/winpos.c @@ -434,320 +434,6 @@ void X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, UINT swp_flags, } -/*********************************************************************** - * WINPOS_FindIconPos - * - * Find a suitable place for an iconic window. - */ -static POINT WINPOS_FindIconPos( HWND hwnd, POINT pt ) -{ - RECT rect, rectParent; - HWND parent, child; - HRGN hrgn, tmp; - int xspacing, yspacing; - - parent = GetAncestor( hwnd, GA_PARENT ); - GetClientRect( parent, &rectParent ); - if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) && - (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom)) - return pt; /* The icon already has a suitable position */ - - xspacing = GetSystemMetrics(SM_CXICONSPACING); - yspacing = GetSystemMetrics(SM_CYICONSPACING); - - /* Check if another icon already occupies this spot */ - /* FIXME: this is completely inefficient */ - - hrgn = CreateRectRgn( 0, 0, 0, 0 ); - tmp = CreateRectRgn( 0, 0, 0, 0 ); - for (child = GetWindow( parent, GW_HWNDFIRST ); child; child = GetWindow( child, GW_HWNDNEXT )) - { - WND *childPtr; - if (child == hwnd) continue; - if ((GetWindowLongW( child, GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE)) - continue; - if (!(childPtr = WIN_GetPtr( child )) || childPtr == WND_OTHER_PROCESS) - continue; - SetRectRgn( tmp, childPtr->rectWindow.left, childPtr->rectWindow.top, - childPtr->rectWindow.right, childPtr->rectWindow.bottom ); - CombineRgn( hrgn, hrgn, tmp, RGN_OR ); - WIN_ReleasePtr( childPtr ); - } - DeleteObject( tmp ); - - for (rect.bottom = rectParent.bottom; rect.bottom >= yspacing; rect.bottom -= yspacing) - { - for (rect.left = rectParent.left; rect.left <= rectParent.right - xspacing; rect.left += xspacing) - { - rect.right = rect.left + xspacing; - rect.top = rect.bottom - yspacing; - if (!RectInRegion( hrgn, &rect )) - { - /* No window was found, so it's OK for us */ - pt.x = rect.left + (xspacing - GetSystemMetrics(SM_CXICON)) / 2; - pt.y = rect.top + (yspacing - GetSystemMetrics(SM_CYICON)) / 2; - DeleteObject( hrgn ); - return pt; - } - } - } - DeleteObject( hrgn ); - pt.x = pt.y = 0; - return pt; -} - - -/*********************************************************************** - * WINPOS_MinMaximize - */ -UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) -{ - WND *wndPtr; - UINT swpFlags = 0; - POINT size; - LONG old_style; - WINDOWPLACEMENT wpl; - - TRACE("%p %u\n", hwnd, cmd ); - - wpl.length = sizeof(wpl); - GetWindowPlacement( hwnd, &wpl ); - - if (HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE )) - return SWP_NOSIZE | SWP_NOMOVE; - - if (IsIconic( hwnd )) - { - switch (cmd) - { - case SW_SHOWMINNOACTIVE: - case SW_SHOWMINIMIZED: - case SW_FORCEMINIMIZE: - case SW_MINIMIZE: - return SWP_NOSIZE | SWP_NOMOVE; - } - if (!SendMessageW( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE; - swpFlags |= SWP_NOCOPYBITS; - } - - switch( cmd ) - { - case SW_SHOWMINNOACTIVE: - case SW_SHOWMINIMIZED: - case SW_FORCEMINIMIZE: - case SW_MINIMIZE: - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; - if( wndPtr->dwStyle & WS_MAXIMIZE) wndPtr->flags |= WIN_RESTORE_MAX; - else wndPtr->flags &= ~WIN_RESTORE_MAX; - WIN_ReleasePtr( wndPtr ); - - old_style = WIN_SetStyle( hwnd, WS_MINIMIZE, WS_MAXIMIZE ); - - wpl.ptMinPosition = WINPOS_FindIconPos( hwnd, wpl.ptMinPosition ); - - if (!(old_style & WS_MINIMIZE)) swpFlags |= SWP_STATECHANGED; - SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, - GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) ); - swpFlags |= SWP_NOCOPYBITS; - break; - - case SW_MAXIMIZE: - old_style = GetWindowLongW( hwnd, GWL_STYLE ); - if ((old_style & WS_MAXIMIZE) && (old_style & WS_VISIBLE)) return SWP_NOSIZE | SWP_NOMOVE; - - WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL ); - - old_style = WIN_SetStyle( hwnd, WS_MAXIMIZE, WS_MINIMIZE ); - if (old_style & WS_MINIMIZE) WINPOS_ShowIconTitle( hwnd, FALSE ); - - if (!(old_style & WS_MAXIMIZE)) swpFlags |= SWP_STATECHANGED; - SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); - break; - - case SW_SHOWNOACTIVATE: - case SW_SHOWNORMAL: - case SW_RESTORE: - old_style = WIN_SetStyle( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); - if (old_style & WS_MINIMIZE) - { - BOOL restore_max; - - WINPOS_ShowIconTitle( hwnd, FALSE ); - - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; - restore_max = (wndPtr->flags & WIN_RESTORE_MAX) != 0; - WIN_ReleasePtr( wndPtr ); - if (restore_max) - { - /* Restore to maximized position */ - WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL); - WIN_SetStyle( hwnd, WS_MAXIMIZE, 0 ); - swpFlags |= SWP_STATECHANGED; - SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); - break; - } - } - else if (!(old_style & WS_MAXIMIZE)) break; - - swpFlags |= SWP_STATECHANGED; - - /* Restore to normal position */ - - *rect = wpl.rcNormalPosition; - rect->right -= rect->left; - rect->bottom -= rect->top; - - break; - } - - return swpFlags; -} - - -/*********************************************************************** - * ShowWindow (X11DRV.@) - */ -BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd ) -{ - WND *wndPtr; - HWND parent; - LONG style = GetWindowLongW( hwnd, GWL_STYLE ); - BOOL wasVisible = (style & WS_VISIBLE) != 0; - BOOL showFlag = TRUE; - RECT newPos = {0, 0, 0, 0}; - UINT swp = 0; - - TRACE("hwnd=%p, cmd=%d, wasVisible %d\n", hwnd, cmd, wasVisible); - - switch(cmd) - { - case SW_HIDE: - if (!wasVisible) return FALSE; - showFlag = FALSE; - swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if (hwnd != GetActiveWindow()) - swp |= SWP_NOACTIVATE | SWP_NOZORDER; - break; - - case SW_SHOWMINNOACTIVE: - swp |= SWP_NOACTIVATE | SWP_NOZORDER; - /* fall through */ - case SW_MINIMIZE: - case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ - if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER; - /* fall through */ - case SW_SHOWMINIMIZED: - swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; - swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos ); - if ((style & WS_MINIMIZE) && wasVisible) return TRUE; - break; - - case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */ - if (!wasVisible) swp |= SWP_SHOWWINDOW; - swp |= SWP_FRAMECHANGED; - swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos ); - if ((style & WS_MAXIMIZE) && wasVisible) return TRUE; - break; - - case SW_SHOWNA: - swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if (style & WS_CHILD) swp |= SWP_NOZORDER; - break; - case SW_SHOW: - if (wasVisible) return TRUE; - swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER; - break; - - case SW_SHOWNOACTIVATE: - swp |= SWP_NOACTIVATE | SWP_NOZORDER; - /* fall through */ - case SW_RESTORE: - /* fall through */ - case SW_SHOWNORMAL: /* same as SW_NORMAL: */ - case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ - if (!wasVisible) swp |= SWP_SHOWWINDOW; - if (style & (WS_MINIMIZE | WS_MAXIMIZE)) - { - swp |= SWP_FRAMECHANGED; - swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos ); - } - else - { - if (wasVisible) return TRUE; - swp |= SWP_NOSIZE | SWP_NOMOVE; - } - if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER; - break; - } - - if ((showFlag != wasVisible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED)) - { - SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 ); - if (!IsWindow( hwnd )) return wasVisible; - } - - parent = GetAncestor( hwnd, GA_PARENT ); - if (parent && !IsWindowVisible( parent ) && !(swp & SWP_STATECHANGED)) - { - /* if parent is not visible simply toggle WS_VISIBLE and return */ - if (showFlag) WIN_SetStyle( hwnd, WS_VISIBLE, 0 ); - else WIN_SetStyle( hwnd, 0, WS_VISIBLE ); - } - else - SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, - newPos.right, newPos.bottom, LOWORD(swp) ); - - if (cmd == SW_HIDE) - { - HWND hFocus; - - /* FIXME: This will cause the window to be activated irrespective - * of whether it is owned by the same thread. Has to be done - * asynchronously. - */ - - if (hwnd == GetActiveWindow()) - WINPOS_ActivateOtherWindow(hwnd); - - /* Revert focus to parent */ - hFocus = GetFocus(); - if (hwnd == hFocus || IsChild(hwnd, hFocus)) - { - HWND parent = GetAncestor(hwnd, GA_PARENT); - if (parent == GetDesktopWindow()) parent = 0; - SetFocus(parent); - } - } - - if (IsIconic(hwnd)) WINPOS_ShowIconTitle( hwnd, TRUE ); - - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return wasVisible; - - if (wndPtr->flags & WIN_NEED_SIZE) - { - /* should happen only in CreateWindowEx() */ - int wParam = SIZE_RESTORED; - RECT client = wndPtr->rectClient; - - wndPtr->flags &= ~WIN_NEED_SIZE; - if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED; - else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED; - WIN_ReleasePtr( wndPtr ); - - SendMessageW( hwnd, WM_SIZE, wParam, - MAKELONG( client.right - client.left, client.bottom - client.top )); - SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top )); - } - else WIN_ReleasePtr( wndPtr ); - - /* if previous state was minimized Windows sets focus to the window */ - if (style & WS_MINIMIZE) SetFocus( hwnd ); - - return wasVisible; -} - - /********************************************************************** * X11DRV_MapNotify */ diff --git a/include/win.h b/include/win.h index 4ed39f6dd23..209854fcf3a 100644 --- a/include/win.h +++ b/include/win.h @@ -115,8 +115,10 @@ extern LONG WINPOS_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos) DECLSPE extern HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest ) DECLSPEC_HIDDEN; extern void WINPOS_CheckInternalPos( HWND hwnd ) DECLSPEC_HIDDEN; extern void WINPOS_ActivateOtherWindow( HWND hwnd ) DECLSPEC_HIDDEN; +extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) DECLSPEC_HIDDEN; extern BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, - const RECT *window_rect, const RECT *client_rect, const RECT *valid_rects ); + const RECT *window_rect, const RECT *client_rect, + const RECT *valid_rects ) DECLSPEC_HIDDEN; #endif /* __WINE_WIN_H */