From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/user32/combo.c | 4 +- dlls/user32/defwnd.c | 2 +- dlls/user32/dialog.c | 6 +- dlls/user32/driver.c | 8 +- dlls/user32/mdi.c | 12 +- dlls/user32/message.c | 21 +- dlls/user32/nonclient.c | 6 +- dlls/user32/scroll.c | 2 +- dlls/user32/user32.spec | 4 +- dlls/user32/user_main.c | 1 - dlls/user32/win.c | 10 +- dlls/user32/win.h | 6 - dlls/user32/winpos.c | 228 +--------------- dlls/win32u/driver.c | 1 + dlls/win32u/gdiobj.c | 2 + dlls/win32u/input.c | 2 +- dlls/win32u/message.c | 3 + dlls/win32u/ntuser_private.h | 7 +- dlls/win32u/win32u.spec | 4 +- dlls/win32u/win32u_private.h | 4 + dlls/win32u/window.c | 487 ++++++++++++++++++++++++++++++++++- dlls/win32u/wrappers.c | 12 + include/ntuser.h | 1 + 23 files changed, 542 insertions(+), 291 deletions(-)
diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c index b375de5080c..d9123057295 100644 --- a/dlls/user32/combo.c +++ b/dlls/user32/combo.c @@ -1030,7 +1030,7 @@ static void CBRollUp( LPHEADCOMBO lphc, BOOL ok, BOOL bButton ) RECT rect;
lphc->wState &= ~CBF_DROPPED; - ShowWindow( lphc->hWndLBox, SW_HIDE ); + NtUserShowWindow( lphc->hWndLBox, SW_HIDE );
if(GetCapture() == lphc->hWndLBox) { @@ -1419,7 +1419,7 @@ static void CBResetPos(HEADCOMBO *combo, BOOL redraw) if (combo->wState & CBF_DROPPED) { combo->wState &= ~CBF_DROPPED; - ShowWindow(combo->hWndLBox, SW_HIDE); + NtUserShowWindow( combo->hWndLBox, SW_HIDE ); }
if (redraw && !(combo->wState & CBF_NOREDRAW)) diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index 271644bb953..bd1928412e0 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -562,7 +562,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa } else pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP; WIN_ReleasePtr( pWnd ); - ShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE ); + NtUserShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE ); break; }
diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index f9d388d0104..a3efd5b6742 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -702,7 +702,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) { - ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */ + NtUserShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */ } return hwnd; } @@ -793,7 +793,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner ) if (bFirstEmpty) { /* ShowWindow the first time the queue goes empty */ - ShowWindow( hwnd, SW_SHOWNORMAL ); + NtUserShowWindow( hwnd, SW_SHOWNORMAL ); bFirstEmpty = FALSE; } if (!(GetWindowLongW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG)) @@ -821,7 +821,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
if (bFirstEmpty && msg.message == WM_TIMER) { - ShowWindow( hwnd, SW_SHOWNORMAL ); + NtUserShowWindow( hwnd, SW_SHOWNORMAL ); bFirstEmpty = FALSE; } } diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index ada0b8ca2f7..25ed33ff073 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -95,11 +95,6 @@ static void CDECL nulldrv_SetWindowText( HWND hwnd, LPCWSTR text ) { }
-static UINT CDECL nulldrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) -{ - return ~0; /* use default implementation */ -} - static LRESULT CDECL nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ) { return -1; @@ -184,7 +179,7 @@ static struct user_driver_funcs lazy_load_driver = nulldrv_SetWindowIcon, NULL, nulldrv_SetWindowText, - nulldrv_ShowWindow, + NULL, nulldrv_SysCommand, NULL, NULL, @@ -222,7 +217,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v SET_USER_FUNC(MsgWaitForMultipleObjectsEx); SET_USER_FUNC(SetWindowIcon); SET_USER_FUNC(SetWindowText); - SET_USER_FUNC(ShowWindow); SET_USER_FUNC(SysCommand); SET_USER_FUNC(WindowPosChanging); SET_USER_FUNC(WindowPosChanged); diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c index 3d85487f808..19db8382bd0 100644 --- a/dlls/user32/mdi.c +++ b/dlls/user32/mdi.c @@ -514,13 +514,13 @@ static void MDI_SwitchActiveChild( MDICLIENTINFO *ci, HWND hwndTo, BOOL activate { /* restore old MDI child */ SendMessageW( hwndPrev, WM_SETREDRAW, FALSE, 0 ); - ShowWindow( hwndPrev, SW_RESTORE ); + NtUserShowWindow( hwndPrev, SW_RESTORE ); SendMessageW( hwndPrev, WM_SETREDRAW, TRUE, 0 );
/* activate new MDI child */ NtUserSetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); /* maximize new MDI child */ - ShowWindow( hwndTo, SW_MAXIMIZE ); + NtUserShowWindow( hwndTo, SW_MAXIMIZE ); } /* activate new MDI child */ NtUserSetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, @@ -547,7 +547,7 @@ static LRESULT MDIDestroyChild( HWND client, MDICLIENTINFO *ci, MDI_SwitchActiveChild(ci, next, TRUE); else { - ShowWindow(child, SW_HIDE); + NtUserShowWindow( child, SW_HIDE ); if (child == ci->hwndChildMaximized) { HWND frame = GetParent(client); @@ -1133,7 +1133,7 @@ LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM return 0;
case WM_MDIMAXIMIZE: - ShowWindow( (HWND)wParam, SW_MAXIMIZE ); + NtUserShowWindow( (HWND)wParam, SW_MAXIMIZE ); return 0;
case WM_MDINEXT: /* lParam != 0 means previous window */ @@ -1147,7 +1147,7 @@ LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM }
case WM_MDIRESTORE: - ShowWindow( (HWND)wParam, SW_SHOWNORMAL ); + NtUserShowWindow( (HWND)wParam, SW_SHOWNORMAL ); return 0;
case WM_MDISETMENU: @@ -1518,7 +1518,7 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message, SendMessageW( hMaxChild, WM_SETREDRAW, FALSE, 0 );
MDI_RestoreFrameMenu( GetParent(client), hMaxChild ); - ShowWindow( hMaxChild, SW_SHOWNOACTIVATE ); + NtUserShowWindow( hMaxChild, SW_SHOWNOACTIVATE );
SendMessageW( hMaxChild, WM_SETREDRAW, TRUE, 0 ); } diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 0ba540d2e5d..2badec331c1 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -1857,21 +1857,12 @@ static void reply_message( struct received_message_info *info, LRESULT result, B */ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - switch(msg) - { - case WM_WINE_SHOWWINDOW: - if (is_desktop_window( hwnd )) return 0; - return ShowWindow( hwnd, wparam ); - default: - { - MSG m; - m.hwnd = hwnd; - m.message = msg; - m.wParam = wparam; - m.lParam = lparam; - return NtUserCallOneParam( (UINT_PTR)&m, NtUserHandleInternalMessage ); - } - } + MSG m; + m.hwnd = hwnd; + m.message = msg; + m.wParam = wparam; + m.lParam = lparam; + return NtUserCallOneParam( (UINT_PTR)&m, NtUserHandleInternalMessage ); }
/* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index 096674db5f7..a2a49fda27b 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -1557,19 +1557,19 @@ LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
case SC_MINIMIZE: ShowOwnedPopups(hwnd,FALSE); - ShowWindow( hwnd, SW_MINIMIZE ); + NtUserShowWindow( hwnd, SW_MINIMIZE ); break;
case SC_MAXIMIZE: if (IsIconic(hwnd)) ShowOwnedPopups(hwnd,TRUE); - ShowWindow( hwnd, SW_MAXIMIZE ); + NtUserShowWindow( hwnd, SW_MAXIMIZE ); break;
case SC_RESTORE: if (IsIconic(hwnd)) ShowOwnedPopups(hwnd,TRUE); - ShowWindow( hwnd, SW_RESTORE ); + NtUserShowWindow( hwnd, SW_RESTORE ); break;
case SC_CLOSE: diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c index d666707299f..c042b72a344 100644 --- a/dlls/user32/scroll.c +++ b/dlls/user32/scroll.c @@ -1973,7 +1973,7 @@ static BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, BOOL fShowH, BOOL fShowV switch(nBar) { case SB_CTL: - ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE ); + NtUserShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE ); return TRUE;
case SB_BOTH: diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index cb18d9415c9..36ec63c21d4 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -740,8 +740,8 @@ @ stdcall ShowOwnedPopups(long long) @ stdcall ShowScrollBar(long long long) @ stub ShowStartGlass -@ stdcall ShowWindow(long long) -@ stdcall ShowWindowAsync(long long) +@ stdcall ShowWindow(long long) NtUserShowWindow +@ stdcall ShowWindowAsync(long long) NtUserShowWindowAsync @ stdcall ShutdownBlockReasonCreate(long wstr) @ stdcall ShutdownBlockReasonDestroy(long) # @ stub SoftModalMessageBox diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 15293d76c41..5a3db40c93c 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -166,7 +166,6 @@ static const struct user_callbacks user_funcs = SendMessageW, SendNotifyMessageW, ShowCaret, - ShowWindow, WaitForInputIdle, free_win_ptr, MENU_IsMenuActive, diff --git a/dlls/user32/win.c b/dlls/user32/win.c index b0e6b33eb56..4d4199c67fc 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1023,10 +1023,10 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, { /* if the new window is maximized don't bother repainting */ SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 ); - ShowWindow( top_child, SW_SHOWNORMAL ); + NtUserShowWindow( top_child, SW_SHOWNORMAL ); SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 ); } - else ShowWindow( top_child, SW_SHOWNORMAL ); + else NtUserShowWindow( top_child, SW_SHOWNORMAL ); } } } @@ -1303,7 +1303,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, else if (cs->style & WS_MINIMIZE) sw = SW_SHOWMINIMIZED;
- ShowWindow( hwnd, sw ); + NtUserShowWindow( hwnd, sw ); if (cs->dwExStyle & WS_EX_MDICHILD) { SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0); @@ -1399,7 +1399,7 @@ HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExW( DWORD exStyle, LPCWSTR className, BOOL WINAPI CloseWindow( HWND hwnd ) { if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE; - ShowWindow( hwnd, SW_MINIMIZE ); + NtUserShowWindow( hwnd, SW_MINIMIZE ); return TRUE; }
@@ -1410,7 +1410,7 @@ BOOL WINAPI CloseWindow( HWND hwnd ) BOOL WINAPI OpenIcon( HWND hwnd ) { if (!IsIconic( hwnd )) return FALSE; - ShowWindow( hwnd, SW_SHOWNORMAL ); + NtUserShowWindow( hwnd, SW_SHOWNORMAL ); return TRUE; }
diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 89e91a255f9..79a57de6bb9 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -42,7 +42,6 @@ extern WND *WIN_GetPtr( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_GetFullHandle( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_IsCurrentProcess( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_IsCurrentThread( HWND hwnd ) DECLSPEC_HIDDEN; -extern UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_HIDDEN; extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN; extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN; extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN; @@ -94,9 +93,4 @@ static inline void mirror_rect( const RECT *window_rect, RECT *rect ) rect->right = width - tmp; }
-static inline UINT win_get_flags( HWND hwnd ) -{ - return win_set_flags( hwnd, 0, 0 ); -} - #endif /* __WINE_WIN_H */ diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 1951f887351..4ba0c47626d 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -67,7 +67,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); */ void WINAPI SwitchToThisWindow( HWND hwnd, BOOL alt_tab ) { - if (IsIconic( hwnd )) ShowWindow( hwnd, SW_RESTORE ); + if (IsIconic( hwnd )) NtUserShowWindow( hwnd, SW_RESTORE ); else BringWindowToTop( hwnd ); }
@@ -799,228 +799,6 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) }
-/*********************************************************************** - * show_window - * - * Implementation of ShowWindow and ShowWindowAsync. - */ -static BOOL show_window( HWND hwnd, INT cmd ) -{ - WND *wndPtr; - HWND parent; - DPI_AWARENESS_CONTEXT context; - LONG style = GetWindowLongW( hwnd, GWL_STYLE ); - BOOL wasVisible = (style & WS_VISIBLE) != 0; - BOOL showFlag = TRUE; - RECT newPos = {0, 0, 0, 0}; - UINT new_swp, swp = 0; - - TRACE("hwnd=%p, cmd=%d, wasVisible %d\n", hwnd, cmd, wasVisible); - - context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd )); - - switch(cmd) - { - case SW_HIDE: - if (!wasVisible) goto done; - showFlag = FALSE; - swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER; - break; - - case SW_SHOWMINNOACTIVE: - case SW_MINIMIZE: - case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ - 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) goto done; - 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) goto done; - 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) goto done; - 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) goto done; - swp |= SWP_NOSIZE | SWP_NOMOVE; - } - if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER; - break; - default: - goto done; - } - - if ((showFlag != wasVisible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED)) - { - SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 ); - if (!IsWindow( hwnd )) goto done; - } - - if (IsRectEmpty( &newPos )) new_swp = swp; - else if ((new_swp = USER_Driver->pShowWindow( hwnd, cmd, &newPos, swp )) == ~0) - { - if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) new_swp = swp; - else if (IsIconic( hwnd ) && (newPos.left != -32000 || newPos.top != -32000)) - { - OffsetRect( &newPos, -32000 - newPos.left, -32000 - newPos.top ); - new_swp = swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE); - } - else new_swp = swp; - } - swp = new_swp; - - parent = NtUserGetAncestor( 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 - NtUserSetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, - newPos.right - newPos.left, newPos.bottom - newPos.top, 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) - { - HWND parent = NtUserGetAncestor(hwnd, GA_PARENT); - if (parent == GetDesktopWindow()) parent = 0; - NtUserSetFocus( parent ); - } - goto done; - } - - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) goto done; - - if (wndPtr->flags & WIN_NEED_SIZE) - { - /* should happen only in CreateWindowEx() */ - int wParam = SIZE_RESTORED; - RECT client; - LPARAM lparam; - - WIN_GetRectangles( hwnd, COORDS_PARENT, NULL, &client ); - lparam = MAKELONG( client.right - client.left, client.bottom - client.top ); - wndPtr->flags &= ~WIN_NEED_SIZE; - if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED; - else if (wndPtr->dwStyle & WS_MINIMIZE) - { - wParam = SIZE_MINIMIZED; - lparam = 0; - } - WIN_ReleasePtr( wndPtr ); - - SendMessageW( hwnd, WM_SIZE, wParam, lparam ); - 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) - { - NtUserSetFocus( hwnd ); - /* Send a WM_ACTIVATE message for a top level window, even if the window is already active */ - if (NtUserGetAncestor( hwnd, GA_ROOT ) == hwnd && !(swp & SWP_NOACTIVATE)) - SendMessageW( hwnd, WM_ACTIVATE, WA_ACTIVE, 0 ); - } - -done: - SetThreadDpiAwarenessContext( context ); - return wasVisible; -} - - -/*********************************************************************** - * ShowWindowAsync (USER32.@) - * - * doesn't wait; returns immediately. - * used by threads to toggle windows in other (possibly hanging) threads - */ -BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd ) -{ - HWND full_handle; - - if (is_broadcast(hwnd)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - if ((full_handle = WIN_IsCurrentThread( hwnd ))) - return show_window( full_handle, cmd ); - - return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); -} - - -/*********************************************************************** - * ShowWindow (USER32.@) - */ -BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) -{ - HWND full_handle; - - if (is_broadcast(hwnd)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - if ((full_handle = WIN_IsCurrentThread( hwnd ))) - return show_window( full_handle, cmd ); - - if ((cmd == SW_HIDE) && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) - return FALSE; - - if ((cmd == SW_SHOW) && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) - return TRUE; - - return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); -} - - /*********************************************************************** * GetInternalWindowPos (USER32.@) */ @@ -1190,7 +968,7 @@ static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT f wp.rcNormalPosition.bottom - wp.rcNormalPosition.top, SWP_NOZORDER | SWP_NOACTIVATE );
- ShowWindow( hwnd, wndpl->showCmd ); + NtUserShowWindow( hwnd, wndpl->showCmd );
if (IsIconic( hwnd )) { @@ -1237,7 +1015,7 @@ BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags) return FALSE; }
- ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA)); + NtUserShowWindow( hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA) );
return TRUE; } diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 166c2009dbc..ec8162b0284 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1202,6 +1202,7 @@ static const struct user_driver_funcs lazy_load_driver = .pReleaseDC = nulldrv_ReleaseDC, .pScrollDC = nulldrv_ScrollDC, .pSetFocus = nulldrv_SetFocus, + .pShowWindow = nulldrv_ShowWindow, .pUpdateLayeredWindow = loaderdrv_UpdateLayeredWindow, .pWindowMessage = nulldrv_WindowMessage, /* system parameters */ diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 69607f0e3de..e47271e6108 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1210,6 +1210,8 @@ static struct unix_funcs unix_funcs = NtUserSetWindowRgn, NtUserSetWindowWord, NtUserShowCursor, + NtUserShowWindow, + NtUserShowWindowAsync, NtUserSystemParametersInfo, NtUserSystemParametersInfoForDpi, NtUserToUnicodeEx, diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index bc82d5e17a3..5cd2cdd0970 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1162,7 +1162,7 @@ HWND get_active_window(void) }
/* see GetFocus */ -static HWND get_focus(void) +HWND get_focus(void) { GUITHREADINFO info; info.cbSize = sizeof(info); diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 690de6cdf8a..853182b6e94 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -46,6 +46,9 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar case WM_WINE_SETWINDOWPOS: if (is_desktop_window( hwnd )) return 0; return set_window_pos( (WINDOWPOS *)lparam, 0, 0 ); + case WM_WINE_SHOWWINDOW: + if (is_desktop_window( hwnd )) return 0; + return NtUserShowWindow( hwnd, wparam ); case WM_WINE_SETPARENT: if (is_desktop_window( hwnd )) return 0; return HandleToUlong( NtUserSetParent( hwnd, UlongToHandle(wparam) )); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 51f17f63de5..49fd22ca140 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -42,7 +42,6 @@ struct user_callbacks LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM ); BOOL (WINAPI *pSendNotifyMessageW)( HWND, UINT, WPARAM, LPARAM ); BOOL (WINAPI *pShowCaret)( HWND hwnd ); - BOOL (WINAPI *pShowWindow)( HWND, INT ); DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD ); void (CDECL *free_win_ptr)( struct tagWND *win ); HWND (CDECL *is_menu_active)(void); @@ -278,6 +277,12 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_ void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN; void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN; void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN; +UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_HIDDEN; + +static inline UINT win_get_flags( HWND hwnd ) +{ + return win_set_flags( hwnd, 0, 0 ); +}
WND *get_win_ptr( HWND hwnd ) DECLSPEC_HIDDEN; BOOL is_child( HWND parent, HWND child ); diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index aacfebd1b15..68348db4033 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1261,8 +1261,8 @@ @ stdcall NtUserShowCursor(long) @ stub NtUserShowScrollBar @ stub NtUserShowSystemCursor -@ stub NtUserShowWindow -@ stub NtUserShowWindowAsync +@ stdcall NtUserShowWindow(long long) +@ stdcall NtUserShowWindowAsync(long long) @ stub NtUserShutdownBlockReasonCreate @ stub NtUserShutdownBlockReasonQuery @ stub NtUserShutdownReasonDestroy diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 2e8a8e3da8e..361bec31ec8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -258,6 +258,8 @@ struct unix_funcs int (WINAPI *pNtUserSetWindowRgn)( HWND hwnd, HRGN hrgn, BOOL redraw ); WORD (WINAPI *pNtUserSetWindowWord)( HWND hwnd, INT offset, WORD newval ); INT (WINAPI *pNtUserShowCursor)( BOOL show ); + BOOL (WINAPI *pNtUserShowWindow)( HWND hwnd, INT cmd ); + BOOL (WINAPI *pNtUserShowWindowAsync)( HWND hwnd, INT cmd ); BOOL (WINAPI *pNtUserSystemParametersInfo)( UINT action, UINT val, PVOID ptr, UINT winini ); BOOL (WINAPI *pNtUserSystemParametersInfoForDpi)( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi ); @@ -311,6 +313,7 @@ extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN; extern LONG global_key_state_counter DECLSPEC_HIDDEN; extern HWND get_active_window(void) DECLSPEC_HIDDEN; extern BOOL get_cursor_pos( POINT *pt ) DECLSPEC_HIDDEN; +extern HWND get_focus(void) DECLSPEC_HIDDEN; extern DWORD get_input_state(void) DECLSPEC_HIDDEN; extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN; extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN; @@ -353,6 +356,7 @@ struct tagWND; extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN; extern void destroy_thread_windows(void) DECLSPEC_HIDDEN; extern LRESULT destroy_window( HWND hwnd ) DECLSPEC_HIDDEN; +extern BOOL get_client_rect( HWND hwnd, RECT *rect ) DECLSPEC_HIDDEN; extern HWND get_desktop_window(void) DECLSPEC_HIDDEN; extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND get_full_window_handle( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 1069ace0794..ab69096184c 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -916,6 +916,11 @@ BOOL is_iconic( HWND hwnd ) return (get_window_long( hwnd, GWL_STYLE ) & WS_MINIMIZE) != 0; }
+static BOOL is_zoomed( HWND hwnd ) +{ + return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0; +} + static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi ) { LONG_PTR retval = 0; @@ -1655,7 +1660,7 @@ BOOL get_window_rect( HWND hwnd, RECT *rect, UINT dpi ) }
/* see GetClientRect */ -static BOOL get_client_rect( HWND hwnd, RECT *rect ) +BOOL get_client_rect( HWND hwnd, RECT *rect ) { return get_window_rects( hwnd, COORDS_CLIENT, NULL, rect, get_thread_dpi() ); } @@ -2174,14 +2179,6 @@ BOOL get_window_placement( HWND hwnd, WINDOWPLACEMENT *placement ) return TRUE; }
-/***************************************************************************** - * NtUserShowWindow (win32u.@) - */ -BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd ) -{ - return user_callbacks && user_callbacks->pShowWindow( hwnd, cmd ); -} - /***************************************************************************** * NtUserBuildHwndList (win32u.@) */ @@ -3179,7 +3176,7 @@ BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async ) * * Set the flags of a window and return the previous value. */ -static UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) +UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) { WND *win = get_win_ptr( hwnd ); UINT ret; @@ -3361,6 +3358,255 @@ static MINMAXINFO get_min_max_info( HWND hwnd ) return minmax; }
+static POINT get_first_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm, + int width, int height ) +{ + POINT ret; + + if (mm->iArrange & ARW_STARTRIGHT) + ret.x = parent->right - mm->iHorzGap - width; + else + ret.x = parent->left + mm->iHorzGap; + if (mm->iArrange & ARW_STARTTOP) + ret.y = parent->top + mm->iVertGap; + else + ret.y = parent->bottom - mm->iVertGap - height; + + return ret; +} + +static void get_next_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm, + int width, int height, POINT *pos ) +{ + BOOL next; + + if (mm->iArrange & ARW_UP) /* == ARW_DOWN */ + { + if (mm->iArrange & ARW_STARTTOP) + { + pos->y += height + mm->iVertGap; + if ((next = pos->y + height > parent->bottom)) + pos->y = parent->top + mm->iVertGap; + } + else + { + pos->y -= height + mm->iVertGap; + if ((next = pos->y < parent->top)) + pos->y = parent->bottom - mm->iVertGap - height; + } + + if (next) + { + if (mm->iArrange & ARW_STARTRIGHT) + pos->x -= width + mm->iHorzGap; + else + pos->x += width + mm->iHorzGap; + } + } + else + { + if (mm->iArrange & ARW_STARTRIGHT) + { + pos->x -= width + mm->iHorzGap; + if ((next = pos->x < parent->left)) + pos->x = parent->right - mm->iHorzGap - width; + } + else + { + pos->x += width + mm->iHorzGap; + if ((next = pos->x + width > parent->right)) + pos->x = parent->left + mm->iHorzGap; + } + + if (next) + { + if (mm->iArrange & ARW_STARTTOP) + pos->y += height + mm->iVertGap; + else + pos->y -= height + mm->iVertGap; + } + } +} + +static POINT get_minimized_pos( HWND hwnd, POINT pt ) +{ + RECT rect, parent_rect; + HWND parent, child; + HRGN hrgn, tmp; + MINIMIZEDMETRICS metrics; + int width, height; + + parent = NtUserGetAncestor( hwnd, GA_PARENT ); + if (parent == get_desktop_window()) + { + MONITORINFO mon_info; + HMONITOR monitor = monitor_from_window( hwnd, MONITOR_DEFAULTTOPRIMARY, get_thread_dpi() ); + + mon_info.cbSize = sizeof( mon_info ); + get_monitor_info( monitor, &mon_info ); + parent_rect = mon_info.rcWork; + } + else get_client_rect( parent, &parent_rect ); + + if (pt.x >= parent_rect.left && (pt.x + get_system_metrics( SM_CXMINIMIZED ) < parent_rect.right) && + pt.y >= parent_rect.top && (pt.y + get_system_metrics( SM_CYMINIMIZED ) < parent_rect.bottom)) + return pt; /* The icon already has a suitable position */ + + width = get_system_metrics( SM_CXMINIMIZED ); + height = get_system_metrics( SM_CYMINIMIZED ); + + metrics.cbSize = sizeof(metrics); + NtUserSystemParametersInfo( SPI_GETMINIMIZEDMETRICS, sizeof(metrics), &metrics, 0 ); + + /* Check if another icon already occupies this spot */ + /* FIXME: this is completely inefficient */ + + hrgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + tmp = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + for (child = get_window_relative( parent, GW_CHILD ); + child; + child = get_window_relative( child, GW_HWNDNEXT )) + { + if (child == hwnd) continue; + if ((get_window_long( child, GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE)) + continue; + if (get_window_rects( child, COORDS_PARENT, &rect, NULL, get_thread_dpi() )) + { + NtGdiSetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom ); + NtGdiCombineRgn( hrgn, hrgn, tmp, RGN_OR ); + } + } + NtGdiDeleteObjectApp( tmp ); + + pt = get_first_minimized_child_pos( &parent_rect, &metrics, width, height ); + for (;;) + { + set_rect( &rect, pt.x, pt.y, pt.x + width, pt.y + height ); + if (!NtGdiRectInRegion( hrgn, &rect )) + break; + + get_next_minimized_child_pos( &parent_rect, &metrics, width, height, &pt ); + } + + NtGdiDeleteObjectApp( hrgn ); + return pt; +} + +/*********************************************************************** + * window_min_maximize + */ +static UINT window_min_maximize( HWND hwnd, UINT cmd, RECT *rect ) +{ + UINT swp_flags = 0; + LONG old_style; + MINMAXINFO minmax; + WINDOWPLACEMENT wpl; + + TRACE( "%p %u\n", hwnd, cmd ); + + wpl.length = sizeof(wpl); + get_window_placement( hwnd, &wpl ); + + if (call_hooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE )) + return SWP_NOSIZE | SWP_NOMOVE; + + if (is_iconic( hwnd )) + { + switch (cmd) + { + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: + case SW_MINIMIZE: + wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition ); + + set_rect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, + wpl.ptMinPosition.x + get_system_metrics( SM_CXMINIMIZED ), + wpl.ptMinPosition.y + get_system_metrics( SM_CYMINIMIZED )); + return SWP_NOSIZE | SWP_NOMOVE; + } + if (!send_message( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE; + swp_flags |= SWP_NOCOPYBITS; + } + + switch( cmd ) + { + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: + case SW_MINIMIZE: + if (is_zoomed( hwnd )) win_set_flags( hwnd, WIN_RESTORE_MAX, 0 ); + else win_set_flags( hwnd, 0, WIN_RESTORE_MAX ); + + if (get_focus() == hwnd) + { + if (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) + NtUserSetFocus( NtUserGetAncestor( hwnd, GA_PARENT )); + else + NtUserSetFocus( 0 ); + } + + old_style = set_window_style( hwnd, WS_MINIMIZE, WS_MAXIMIZE ); + + wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition ); + + if (!(old_style & WS_MINIMIZE)) swp_flags |= SWP_STATECHANGED; + set_rect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, + wpl.ptMinPosition.x + get_system_metrics(SM_CXMINIMIZED), + wpl.ptMinPosition.y + get_system_metrics(SM_CYMINIMIZED) ); + swp_flags |= SWP_NOCOPYBITS; + break; + + case SW_MAXIMIZE: + old_style = get_window_long( hwnd, GWL_STYLE ); + if ((old_style & WS_MAXIMIZE) && (old_style & WS_VISIBLE)) return SWP_NOSIZE | SWP_NOMOVE; + + minmax = get_min_max_info( hwnd ); + + old_style = set_window_style( hwnd, WS_MAXIMIZE, WS_MINIMIZE ); + if (old_style & WS_MINIMIZE) + win_set_flags( hwnd, WIN_RESTORE_MAX, 0 ); + + if (!(old_style & WS_MAXIMIZE)) swp_flags |= SWP_STATECHANGED; + set_rect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y, + minmax.ptMaxPosition.x + minmax.ptMaxSize.x, + minmax.ptMaxPosition.y + minmax.ptMaxSize.y ); + break; + + case SW_SHOWNOACTIVATE: + win_set_flags( hwnd, 0, WIN_RESTORE_MAX ); + /* fall through */ + case SW_SHOWNORMAL: + case SW_RESTORE: + case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ + old_style = set_window_style( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); + if (old_style & WS_MINIMIZE) + { + if (win_get_flags( hwnd ) & WIN_RESTORE_MAX) + { + /* Restore to maximized position */ + minmax = get_min_max_info( hwnd ); + set_window_style( hwnd, WS_MAXIMIZE, 0 ); + swp_flags |= SWP_STATECHANGED; + set_rect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y, + minmax.ptMaxPosition.x + minmax.ptMaxSize.x, + minmax.ptMaxPosition.y + minmax.ptMaxSize.y ); + break; + } + } + else if (!(old_style & WS_MAXIMIZE)) break; + + swp_flags |= SWP_STATECHANGED; + + /* Restore to normal position */ + + *rect = wpl.rcNormalPosition; + break; + } + + return swp_flags; +} + /******************************************************************* * update_window_state * @@ -3387,6 +3633,227 @@ void update_window_state( HWND hwnd ) set_thread_dpi_awareness_context( context ); }
+/*********************************************************************** + * show_window + * + * Implementation of ShowWindow and ShowWindowAsync. + */ +static BOOL show_window( HWND hwnd, INT cmd ) +{ + WND *win; + HWND parent; + DPI_AWARENESS_CONTEXT context; + LONG style = get_window_long( hwnd, GWL_STYLE ); + BOOL was_visible = (style & WS_VISIBLE) != 0; + BOOL show_flag = TRUE; + RECT newPos = {0, 0, 0, 0}; + UINT new_swp, swp = 0; + + TRACE( "hwnd=%p, cmd=%d, was_visible %d\n", hwnd, cmd, was_visible ); + + context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd )); + + switch(cmd) + { + case SW_HIDE: + if (!was_visible) goto done; + show_flag = FALSE; + swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; + if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER; + break; + + case SW_SHOWMINNOACTIVE: + case SW_MINIMIZE: + case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ + swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* fall through */ + case SW_SHOWMINIMIZED: + swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; + swp |= window_min_maximize( hwnd, cmd, &newPos ); + if ((style & WS_MINIMIZE) && was_visible) goto done; + break; + + case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */ + if (!was_visible) swp |= SWP_SHOWWINDOW; + swp |= SWP_FRAMECHANGED; + swp |= window_min_maximize( hwnd, SW_MAXIMIZE, &newPos ); + if ((style & WS_MAXIMIZE) && was_visible) goto done; + 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 (was_visible) goto done; + 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 (!was_visible) swp |= SWP_SHOWWINDOW; + if (style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + swp |= SWP_FRAMECHANGED; + swp |= window_min_maximize( hwnd, cmd, &newPos ); + } + else + { + if (was_visible) goto done; + swp |= SWP_NOSIZE | SWP_NOMOVE; + } + if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER; + break; + + default: + goto done; + } + + if ((show_flag != was_visible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED)) + { + send_message( hwnd, WM_SHOWWINDOW, show_flag, 0 ); + if (!is_window( hwnd )) goto done; + } + + if (IsRectEmpty( &newPos )) new_swp = swp; + else if ((new_swp = user_driver->pShowWindow( hwnd, cmd, &newPos, swp )) == ~0) + { + if (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) new_swp = swp; + else if (is_iconic( hwnd ) && (newPos.left != -32000 || newPos.top != -32000)) + { + offset_rect( &newPos, -32000 - newPos.left, -32000 - newPos.top ); + new_swp = swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE); + } + else new_swp = swp; + } + swp = new_swp; + + parent = NtUserGetAncestor( hwnd, GA_PARENT ); + if (parent && !is_window_visible( parent ) && !(swp & SWP_STATECHANGED)) + { + /* if parent is not visible simply toggle WS_VISIBLE and return */ + if (show_flag) set_window_style( hwnd, WS_VISIBLE, 0 ); + else set_window_style( hwnd, 0, WS_VISIBLE ); + } + else + NtUserSetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, + newPos.right - newPos.left, newPos.bottom - newPos.top, 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 == get_active_window()) activate_other_window( hwnd ); + + /* Revert focus to parent */ + hFocus = get_focus(); + if (hwnd == hFocus) + { + HWND parent = NtUserGetAncestor(hwnd, GA_PARENT); + if (parent == get_desktop_window()) parent = 0; + NtUserSetFocus(parent); + } + goto done; + } + + if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) goto done; + + if (win->flags & WIN_NEED_SIZE) + { + /* should happen only in CreateWindowEx() */ + int wParam = SIZE_RESTORED; + RECT client; + LPARAM lparam; + + get_window_rects( hwnd, COORDS_PARENT, NULL, &client, get_thread_dpi() ); + lparam = MAKELONG( client.right - client.left, client.bottom - client.top ); + win->flags &= ~WIN_NEED_SIZE; + if (win->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED; + else if (win->dwStyle & WS_MINIMIZE) + { + wParam = SIZE_MINIMIZED; + lparam = 0; + } + release_win_ptr( win ); + + send_message( hwnd, WM_SIZE, wParam, lparam ); + send_message( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top )); + } + else release_win_ptr( win ); + + /* if previous state was minimized Windows sets focus to the window */ + if (style & WS_MINIMIZE) + { + NtUserSetFocus( hwnd ); + /* Send a WM_ACTIVATE message for a top level window, even if the window is already active */ + if (NtUserGetAncestor( hwnd, GA_ROOT ) == hwnd && !(swp & SWP_NOACTIVATE)) + send_message( hwnd, WM_ACTIVATE, WA_ACTIVE, 0 ); + } + +done: + set_thread_dpi_awareness_context( context ); + return was_visible; +} + +/*********************************************************************** + * NtUserShowWindowAsync (win32u.@) + * + * doesn't wait; returns immediately. + * used by threads to toggle windows in other (possibly hanging) threads + */ +BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd ) +{ + HWND full_handle; + + if (is_broadcast(hwnd)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if ((full_handle = is_current_thread_window( hwnd ))) + return show_window( full_handle, cmd ); + + return NtUserMessageCall( hwnd, WM_WINE_SHOWWINDOW, cmd, 0, 0, + FNID_SENDNOTIFYMESSAGE, FALSE ); +} + +/*********************************************************************** + * NtUserShowWindow (win32u.@) + */ +BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd ) +{ + HWND full_handle; + + if (is_broadcast(hwnd)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + if ((full_handle = is_current_thread_window( hwnd ))) + return show_window( full_handle, cmd ); + + if ((cmd == SW_HIDE) && !(get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE)) + return FALSE; + + if ((cmd == SW_SHOW) && (get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE)) + return TRUE; + + return send_message( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); +} + /******************************************************************* * NtUserFlashWindowEx (win32u.@) */ diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index da1957c8c88..6cb3a6896b5 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1075,6 +1075,18 @@ INT WINAPI NtUserShowCursor( BOOL show ) return unix_funcs->pNtUserShowCursor( show ); }
+BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserShowWindowAsync( hwnd, cmd ); +} + +BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserShowWindow( hwnd, cmd ); +} + BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, PVOID ptr, UINT winini ) { if (!unix_funcs) return FALSE; diff --git a/include/ntuser.h b/include/ntuser.h index 274c0cf31c9..6526d190e28 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -422,6 +422,7 @@ HWINEVENTHOOK WINAPI NtUserSetWinEventHook( DWORD event_min, DWORD event_max, HM DWORD pid, DWORD tid, DWORD flags ); INT WINAPI NtUserShowCursor( BOOL show ); BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd ); +BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd ); BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, void *ptr, UINT winini ); BOOL WINAPI NtUserSystemParametersInfoForDpi( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi ); INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,