From 0c752feda6f40cdd514db0847cbe32a1db47003c Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 15 Mar 2022 14:27:55 +0100 Subject: [PATCH] win32u: Move NtUserSetParent implementation from user32. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/user32/combo.c | 2 +- dlls/user32/driver.c | 7 +- dlls/user32/message.c | 3 - dlls/user32/painting.c | 29 -- dlls/user32/user32.spec | 2 +- dlls/user32/user_main.c | 1 + dlls/user32/user_private.h | 3 - dlls/user32/win.c | 104 +------ dlls/user32/winpos.c | 507 ----------------------------------- dlls/win32u/driver.c | 1 + dlls/win32u/gdiobj.c | 1 + dlls/win32u/message.c | 3 + dlls/win32u/ntuser_private.h | 1 + dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 2 + dlls/win32u/window.c | 107 +++++++- dlls/win32u/wrappers.c | 6 + include/ntuser.h | 2 + 18 files changed, 128 insertions(+), 655 deletions(-) diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c index 3c8731514c1..77cb24be064 100644 --- a/dlls/user32/combo.c +++ b/dlls/user32/combo.c @@ -548,7 +548,7 @@ static LRESULT COMBO_Create( HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG if( CB_GETTYPE(lphc) != CBS_SIMPLE ) { /* Now do the trick with parent */ - SetParent(lphc->hWndLBox, HWND_DESKTOP); + NtUserSetParent( lphc->hWndLBox, HWND_DESKTOP ); /* * If the combo is a dropdown, we must resize the control * to fit only the text area and button. To do this, diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 9f3ad85ac19..1d6c36c5434 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -91,10 +91,6 @@ static DWORD CDECL nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDL timeout, flags & MWMO_ALERTABLE ); } -static void CDECL nulldrv_SetParent( HWND hwnd, HWND parent, HWND old_parent ) -{ -} - static void CDECL nulldrv_SetWindowIcon( HWND hwnd, UINT type, HICON icon ) { } @@ -191,7 +187,7 @@ static struct user_driver_funcs lazy_load_driver = NULL, NULL, NULL, - nulldrv_SetParent, + NULL, NULL, nulldrv_SetWindowIcon, nulldrv_SetWindowStyle, @@ -233,7 +229,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v SET_USER_FUNC(CreateWindow); SET_USER_FUNC(DestroyWindow); SET_USER_FUNC(MsgWaitForMultipleObjectsEx); - SET_USER_FUNC(SetParent); SET_USER_FUNC(SetWindowIcon); SET_USER_FUNC(SetWindowStyle); SET_USER_FUNC(SetWindowText); diff --git a/dlls/user32/message.c b/dlls/user32/message.c index a808deeb883..27a83dc662b 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -1864,9 +1864,6 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar case WM_WINE_SHOWWINDOW: if (is_desktop_window( hwnd )) return 0; return ShowWindow( hwnd, wparam ); - case WM_WINE_SETPARENT: - if (is_desktop_window( hwnd )) return 0; - return (LRESULT)SetParent( hwnd, (HWND)wparam ); case WM_WINE_SETWINDOWLONG: return WIN_SetWindowLong( hwnd, (short)LOWORD(wparam), HIWORD(wparam), lparam, TRUE ); case WM_WINE_SETSTYLE: diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index f55bc79afdd..eceeaaf1082 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -291,35 +291,6 @@ static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn, } -/*********************************************************************** - * erase_now - * - * Implementation of RDW_ERASENOW behavior. - */ -void erase_now( HWND hwnd, UINT rdw_flags ) -{ - HWND child = 0; - HRGN hrgn; - BOOL need_erase = FALSE; - - /* loop while we find a child to repaint */ - for (;;) - { - UINT flags = UPDATE_NONCLIENT | UPDATE_ERASE; - - if (rdw_flags & RDW_NOCHILDREN) flags |= UPDATE_NOCHILDREN; - else if (rdw_flags & RDW_ALLCHILDREN) flags |= UPDATE_ALLCHILDREN; - if (need_erase) flags |= UPDATE_DELAYED_ERASE; - - if (!(hrgn = send_ncpaint( hwnd, &child, &flags ))) break; - need_erase = send_erase( child, flags, hrgn, NULL, NULL ); - - if (!flags) break; /* nothing more to do */ - if ((rdw_flags & RDW_NOCHILDREN) && !need_erase) break; - } -} - - /*********************************************************************** * copy_bits_from_surface * diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 0622053fe60..bb20ce3f332 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -686,7 +686,7 @@ @ stdcall SetMenuItemInfoW(long long long ptr) @ stdcall SetMessageExtraInfo(long) @ stdcall SetMessageQueue(long) -@ stdcall SetParent(long long) +@ stdcall SetParent(long long) NtUserSetParent @ stdcall SetPhysicalCursorPos(long long) @ stdcall SetProcessDPIAware() @ stdcall SetProcessDefaultLayout(long) diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 06f0ca47449..8e8c357bdcf 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -150,6 +150,7 @@ static const struct user_callbacks user_funcs = SendMessageW, SendNotifyMessageW, ShowCaret, + ShowWindow, WaitForInputIdle, notify_ime, register_builtin_classes, diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index b5bd5fd4851..465522e54dc 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -106,7 +106,6 @@ extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN; extern HDC get_display_dc(void) DECLSPEC_HIDDEN; extern void release_display_dc( HDC hdc ) DECLSPEC_HIDDEN; -extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN; extern void move_window_bits( HWND hwnd, struct window_surface *old_surface, struct window_surface *new_surface, const RECT *visible_rect, const RECT *old_visible_rect, @@ -129,8 +128,6 @@ extern void SYSPARAMS_Init(void) DECLSPEC_HIDDEN; extern void USER_CheckNotLock(void) DECLSPEC_HIDDEN; extern BOOL USER_IsExitingThread( DWORD tid ) DECLSPEC_HIDDEN; -extern BOOL USER_SetWindowPos( WINDOWPOS * winpos, int parent_x, int parent_y ) DECLSPEC_HIDDEN; - typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg ); diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 69cad497407..ca4697713d6 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -2118,7 +2118,7 @@ LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, B else { WIN_ReleasePtr( wndPtr ); - return (ULONG_PTR)SetParent( hwnd, (HWND)newval ); + return (ULONG_PTR)NtUserSetParent( hwnd, (HWND)newval ); } case GWLP_WNDPROC: { @@ -2610,108 +2610,6 @@ HWND WINAPI GetParent( HWND hwnd ) } -/***************************************************************** - * SetParent (USER32.@) - */ -HWND WINAPI SetParent( HWND hwnd, HWND parent ) -{ - WINDOWPOS winpos; - HWND full_handle; - HWND old_parent = 0; - BOOL was_visible; - WND *wndPtr; - BOOL ret; - DPI_AWARENESS_CONTEXT context; - RECT window_rect, old_screen_rect, new_screen_rect; - - TRACE("(%p %p)\n", hwnd, parent); - - if (is_broadcast(hwnd) || is_broadcast(parent)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - if (!parent) parent = GetDesktopWindow(); - else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent(); - else parent = WIN_GetFullHandle( parent ); - - if (!IsWindow( parent )) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return 0; - } - - /* Some applications try to set a child as a parent */ - if (IsChild(hwnd, parent)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - - if (!(full_handle = WIN_IsCurrentThread( hwnd ))) - return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 ); - - if (full_handle == parent) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - - /* Windows hides the window first, then shows it again - * including the WM_SHOWWINDOW messages and all */ - was_visible = ShowWindow( hwnd, SW_HIDE ); - - wndPtr = WIN_GetPtr( hwnd ); - if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0; - - context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd )); - WIN_GetRectangles( hwnd, COORDS_PARENT, &window_rect, NULL ); - SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ); - WIN_GetRectangles( hwnd, COORDS_SCREEN, &old_screen_rect, NULL ); - SetThreadDpiAwarenessContext( context ); - - SERVER_START_REQ( set_parent ) - { - req->handle = wine_server_user_handle( hwnd ); - req->parent = wine_server_user_handle( parent ); - if ((ret = !wine_server_call_err( req ))) - { - old_parent = wine_server_ptr_handle( reply->old_parent ); - wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent ); - wndPtr->dpi = reply->dpi; - wndPtr->dpi_awareness = reply->awareness; - } - - } - SERVER_END_REQ; - WIN_ReleasePtr( wndPtr ); - if (!ret) return 0; - - context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ); - WIN_GetRectangles( hwnd, COORDS_SCREEN, &new_screen_rect, NULL ); - SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd )); - - USER_Driver->pSetParent( full_handle, parent, old_parent ); - - winpos.hwnd = hwnd; - winpos.hwndInsertAfter = HWND_TOP; - winpos.x = window_rect.left; - winpos.y = window_rect.top; - winpos.cx = 0; - winpos.cy = 0; - winpos.flags = SWP_NOSIZE; - - USER_SetWindowPos( &winpos, new_screen_rect.left - old_screen_rect.left, - new_screen_rect.top - old_screen_rect.top ); - - if (was_visible) ShowWindow( hwnd, SW_SHOW ); - - SetThreadDpiAwarenessContext( context ); - return old_parent; -} - - /******************************************************************* * IsChild (USER32.@) */ diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index ecc7552cd75..b3e8aff3cfa 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -1441,382 +1441,6 @@ LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos ) } -/*********************************************************************** - * SWP_DoWinPosChanging - */ -static BOOL SWP_DoWinPosChanging( WINDOWPOS *pWinpos, RECT *old_window_rect, RECT *old_client_rect, - RECT *new_window_rect, RECT *new_client_rect ) -{ - WND *wndPtr; - - /* Send WM_WINDOWPOSCHANGING message */ - - if (!(pWinpos->flags & SWP_NOSENDCHANGING) - && !((pWinpos->flags & SWP_AGG_NOCLIENTCHANGE) && (pWinpos->flags & SWP_SHOWWINDOW))) - SendMessageW( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos ); - - if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || - wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE; - - /* Calculate new position and size */ - - WIN_GetRectangles( pWinpos->hwnd, COORDS_PARENT, old_window_rect, old_client_rect ); - *new_window_rect = *old_window_rect; - *new_client_rect = *old_client_rect; - - if (!(pWinpos->flags & SWP_NOSIZE)) - { - if (wndPtr->dwStyle & WS_MINIMIZE) - { - new_window_rect->right = new_window_rect->left + GetSystemMetrics(SM_CXMINIMIZED); - new_window_rect->bottom = new_window_rect->top + GetSystemMetrics(SM_CYMINIMIZED); - } - else - { - new_window_rect->right = new_window_rect->left + pWinpos->cx; - new_window_rect->bottom = new_window_rect->top + pWinpos->cy; - } - } - if (!(pWinpos->flags & SWP_NOMOVE)) - { - /* If the window is toplevel minimized off-screen, force keep it there */ - if ((wndPtr->dwStyle & WS_MINIMIZE) && - wndPtr->window_rect.left <= -32000 && wndPtr->window_rect.top <= -32000 && - (!wndPtr->parent || wndPtr->parent == GetDesktopWindow())) - { - pWinpos->x = -32000; - pWinpos->y = -32000; - } - new_window_rect->left = pWinpos->x; - new_window_rect->top = pWinpos->y; - new_window_rect->right += pWinpos->x - old_window_rect->left; - new_window_rect->bottom += pWinpos->y - old_window_rect->top; - - OffsetRect( new_client_rect, pWinpos->x - old_window_rect->left, - pWinpos->y - old_window_rect->top ); - } - pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; - - TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x current %s style %08x new %s\n", - pWinpos->hwnd, pWinpos->hwndInsertAfter, pWinpos->x, pWinpos->y, - pWinpos->cx, pWinpos->cy, pWinpos->flags, - wine_dbgstr_rect( old_window_rect ), wndPtr->dwStyle, - wine_dbgstr_rect( new_window_rect )); - - WIN_ReleasePtr( wndPtr ); - return TRUE; -} - -/*********************************************************************** - * get_valid_rects - * - * Compute the valid rects from the old and new client rect and WVR_* flags. - * Helper for WM_NCCALCSIZE handling. - */ -static inline void get_valid_rects( const RECT *old_client, const RECT *new_client, UINT flags, - RECT *valid ) -{ - int cx, cy; - - if (flags & WVR_REDRAW) - { - SetRectEmpty( &valid[0] ); - SetRectEmpty( &valid[1] ); - return; - } - - if (flags & WVR_VALIDRECTS) - { - if (!IntersectRect( &valid[0], &valid[0], new_client ) || - !IntersectRect( &valid[1], &valid[1], old_client )) - { - SetRectEmpty( &valid[0] ); - SetRectEmpty( &valid[1] ); - return; - } - flags = WVR_ALIGNLEFT | WVR_ALIGNTOP; - } - else - { - valid[0] = *new_client; - valid[1] = *old_client; - } - - /* make sure the rectangles have the same size */ - cx = min( valid[0].right - valid[0].left, valid[1].right - valid[1].left ); - cy = min( valid[0].bottom - valid[0].top, valid[1].bottom - valid[1].top ); - - if (flags & WVR_ALIGNBOTTOM) - { - valid[0].top = valid[0].bottom - cy; - valid[1].top = valid[1].bottom - cy; - } - else - { - valid[0].bottom = valid[0].top + cy; - valid[1].bottom = valid[1].top + cy; - } - if (flags & WVR_ALIGNRIGHT) - { - valid[0].left = valid[0].right - cx; - valid[1].left = valid[1].right - cx; - } - else - { - valid[0].right = valid[0].left + cx; - valid[1].right = valid[1].left + cx; - } -} - - -/*********************************************************************** - * SWP_DoOwnedPopups - * - * fix Z order taking into account owned popups - - * basically we need to maintain them above the window that owns them - * - * FIXME: hide/show owned popups when owner visibility changes. - */ -static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter) -{ - HWND owner, *list = NULL; - unsigned int i; - - TRACE("(%p) hInsertAfter = %p\n", hwnd, hwndInsertAfter ); - - if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return hwndInsertAfter; - - if ((owner = GetWindow( hwnd, GW_OWNER ))) - { - /* make sure this popup stays above the owner */ - - if (hwndInsertAfter != HWND_TOPMOST) - { - if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return hwndInsertAfter; - - for (i = 0; list[i]; i++) - { - BOOL topmost = (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TOPMOST) != 0; - - if (list[i] == owner) - { - if (i > 0) hwndInsertAfter = list[i-1]; - else hwndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP; - break; - } - - if (hwndInsertAfter == HWND_TOP || hwndInsertAfter == HWND_NOTOPMOST) - { - if (!topmost) break; - } - else if (list[i] == hwndInsertAfter) break; - } - } - } - - if (hwndInsertAfter == HWND_BOTTOM) goto done; - if (!list && !(list = WIN_ListChildren( GetDesktopWindow() ))) goto done; - - i = 0; - if (hwndInsertAfter == HWND_TOP || hwndInsertAfter == HWND_NOTOPMOST) - { - if (hwndInsertAfter == HWND_NOTOPMOST || !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOPMOST)) - { - /* skip all the topmost windows */ - while (list[i] && (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TOPMOST)) i++; - } - } - else if (hwndInsertAfter != HWND_TOPMOST) - { - /* skip windows that are already placed correctly */ - for (i = 0; list[i]; i++) - { - if (list[i] == hwndInsertAfter) break; - if (list[i] == hwnd) goto done; /* nothing to do if window is moving backwards in z-order */ - } - } - - for ( ; list[i]; i++) - { - if (list[i] == hwnd) break; - if (GetWindow( list[i], GW_OWNER ) != hwnd) continue; - TRACE( "moving %p owned by %p after %p\n", list[i], hwnd, hwndInsertAfter ); - NtUserSetWindowPos( list[i], hwndInsertAfter, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE ); - hwndInsertAfter = list[i]; - } - -done: - HeapFree( GetProcessHeap(), 0, list ); - return hwndInsertAfter; -} - -/*********************************************************************** - * SWP_DoNCCalcSize - */ -static UINT SWP_DoNCCalcSize( WINDOWPOS *pWinpos, const RECT *old_window_rect, const RECT *old_client_rect, - const RECT *new_window_rect, RECT *new_client_rect, RECT *validRects, - int parent_x, int parent_y ) -{ - UINT wvrFlags = 0; - - /* Send WM_NCCALCSIZE message to get new client area */ - if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE ) - { - NCCALCSIZE_PARAMS params; - WINDOWPOS winposCopy; - - params.rgrc[0] = *new_window_rect; - params.rgrc[1] = *old_window_rect; - params.rgrc[2] = *old_client_rect; - params.lppos = &winposCopy; - winposCopy = *pWinpos; - - if (pWinpos->flags & SWP_NOMOVE) - { - winposCopy.x = old_window_rect->left; - winposCopy.y = old_window_rect->top; - } - - if (pWinpos->flags & SWP_NOSIZE) - { - winposCopy.cx = old_window_rect->right - old_window_rect->left; - winposCopy.cy = old_window_rect->bottom - old_window_rect->top; - } - - wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)¶ms ); - - *new_client_rect = params.rgrc[0]; - - TRACE( "hwnd %p old win %s old client %s new win %s new client %s\n", pWinpos->hwnd, - wine_dbgstr_rect(old_window_rect), wine_dbgstr_rect(old_client_rect), - wine_dbgstr_rect(new_window_rect), wine_dbgstr_rect(new_client_rect) ); - - if (new_client_rect->left != old_client_rect->left - parent_x || - new_client_rect->top != old_client_rect->top - parent_y) - pWinpos->flags &= ~SWP_NOCLIENTMOVE; - - if( (new_client_rect->right - new_client_rect->left != - old_client_rect->right - old_client_rect->left)) - pWinpos->flags &= ~SWP_NOCLIENTSIZE; - else - wvrFlags &= ~WVR_HREDRAW; - - if (new_client_rect->bottom - new_client_rect->top != - old_client_rect->bottom - old_client_rect->top) - pWinpos->flags &= ~SWP_NOCLIENTSIZE; - else - wvrFlags &= ~WVR_VREDRAW; - - validRects[0] = params.rgrc[1]; - validRects[1] = params.rgrc[2]; - } - else - { - if (!(pWinpos->flags & SWP_NOMOVE) && - (new_client_rect->left != old_client_rect->left - parent_x || - new_client_rect->top != old_client_rect->top - parent_y)) - pWinpos->flags &= ~SWP_NOCLIENTMOVE; - } - - if (pWinpos->flags & (SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_HIDEWINDOW)) - { - SetRectEmpty( &validRects[0] ); - SetRectEmpty( &validRects[1] ); - } - else get_valid_rects( old_client_rect, new_client_rect, wvrFlags, validRects ); - - return wvrFlags; -} - -/* fix redundant flags and values in the WINDOWPOS structure */ -static BOOL fixup_flags( WINDOWPOS *winpos, const RECT *old_window_rect, int parent_x, int parent_y ) -{ - HWND parent; - WND *wndPtr = WIN_GetPtr( winpos->hwnd ); - BOOL ret = TRUE; - - if (!wndPtr || wndPtr == WND_OTHER_PROCESS) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return FALSE; - } - winpos->hwnd = wndPtr->obj.handle; /* make it a full handle */ - - /* Finally make sure that all coordinates are valid */ - if (winpos->x < -32768) winpos->x = -32768; - else if (winpos->x > 32767) winpos->x = 32767; - if (winpos->y < -32768) winpos->y = -32768; - else if (winpos->y > 32767) winpos->y = 32767; - - if (winpos->cx < 0) winpos->cx = 0; - else if (winpos->cx > 32767) winpos->cx = 32767; - if (winpos->cy < 0) winpos->cy = 0; - else if (winpos->cy > 32767) winpos->cy = 32767; - - parent = NtUserGetAncestor( winpos->hwnd, GA_PARENT ); - if (!IsWindowVisible( parent )) winpos->flags |= SWP_NOREDRAW; - - if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW; - else - { - winpos->flags &= ~SWP_HIDEWINDOW; - if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW; - } - - if ((old_window_rect->right - old_window_rect->left == winpos->cx) && - (old_window_rect->bottom - old_window_rect->top == winpos->cy)) - winpos->flags |= SWP_NOSIZE; /* Already the right size */ - - if ((old_window_rect->left - parent_x == winpos->x) && (old_window_rect->top - parent_y == winpos->y)) - winpos->flags |= SWP_NOMOVE; /* Already the right position */ - - if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD) - { - if (!(winpos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) && /* Bring to the top when activating */ - (winpos->flags & SWP_NOZORDER || - (winpos->hwndInsertAfter != HWND_TOPMOST && winpos->hwndInsertAfter != HWND_NOTOPMOST))) - { - winpos->flags &= ~SWP_NOZORDER; - winpos->hwndInsertAfter = HWND_TOP; - } - } - - /* Check hwndInsertAfter */ - if (winpos->flags & SWP_NOZORDER) goto done; - - if (winpos->hwndInsertAfter == HWND_TOP) - { - if (GetWindow(winpos->hwnd, GW_HWNDFIRST) == winpos->hwnd) - winpos->flags |= SWP_NOZORDER; - } - else if (winpos->hwndInsertAfter == HWND_BOTTOM) - { - if (!(wndPtr->dwExStyle & WS_EX_TOPMOST) && GetWindow(winpos->hwnd, GW_HWNDLAST) == winpos->hwnd) - winpos->flags |= SWP_NOZORDER; - } - else if (winpos->hwndInsertAfter == HWND_TOPMOST) - { - if ((wndPtr->dwExStyle & WS_EX_TOPMOST) && GetWindow(winpos->hwnd, GW_HWNDFIRST) == winpos->hwnd) - winpos->flags |= SWP_NOZORDER; - } - else if (winpos->hwndInsertAfter == HWND_NOTOPMOST) - { - if (!(wndPtr->dwExStyle & WS_EX_TOPMOST)) - winpos->flags |= SWP_NOZORDER; - } - else - { - if ((winpos->hwnd == winpos->hwndInsertAfter) || - (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT ))) - winpos->flags |= SWP_NOZORDER; - } - done: - WIN_ReleasePtr( wndPtr ); - return ret; -} - - /*********************************************************************** * update_surface_region */ @@ -2044,137 +1668,6 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, } -/*********************************************************************** - * USER_SetWindowPos - * - * User32 internal function - */ -BOOL USER_SetWindowPos( WINDOWPOS * winpos, int parent_x, int parent_y ) -{ - RECT old_window_rect, old_client_rect, new_window_rect, new_client_rect, valid_rects[2]; - UINT orig_flags; - BOOL ret = FALSE; - DPI_AWARENESS_CONTEXT context; - - orig_flags = winpos->flags; - - /* First, check z-order arguments. */ - if (!(winpos->flags & SWP_NOZORDER)) - { - /* fix sign extension */ - if (winpos->hwndInsertAfter == (HWND)0xffff) winpos->hwndInsertAfter = HWND_TOPMOST; - else if (winpos->hwndInsertAfter == (HWND)0xfffe) winpos->hwndInsertAfter = HWND_NOTOPMOST; - - if (!(winpos->hwndInsertAfter == HWND_TOP || - winpos->hwndInsertAfter == HWND_BOTTOM || - winpos->hwndInsertAfter == HWND_TOPMOST || - winpos->hwndInsertAfter == HWND_NOTOPMOST)) - { - HWND parent = NtUserGetAncestor( winpos->hwnd, GA_PARENT ); - HWND insertafter_parent = NtUserGetAncestor( winpos->hwndInsertAfter, GA_PARENT ); - - /* hwndInsertAfter must be a sibling of the window */ - if (!insertafter_parent) return FALSE; - if (insertafter_parent != parent) return TRUE; - } - } - - /* Make sure that coordinates are valid for WM_WINDOWPOSCHANGING */ - if (!(winpos->flags & SWP_NOMOVE)) - { - if (winpos->x < -32768) winpos->x = -32768; - else if (winpos->x > 32767) winpos->x = 32767; - if (winpos->y < -32768) winpos->y = -32768; - else if (winpos->y > 32767) winpos->y = 32767; - } - if (!(winpos->flags & SWP_NOSIZE)) - { - if (winpos->cx < 0) winpos->cx = 0; - else if (winpos->cx > 32767) winpos->cx = 32767; - if (winpos->cy < 0) winpos->cy = 0; - else if (winpos->cy > 32767) winpos->cy = 32767; - } - - context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( winpos->hwnd )); - - if (!SWP_DoWinPosChanging( winpos, &old_window_rect, &old_client_rect, - &new_window_rect, &new_client_rect )) goto done; - - /* Fix redundant flags */ - if (!fixup_flags( winpos, &old_window_rect, parent_x, parent_y )) goto done; - - if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER) - { - if (NtUserGetAncestor( winpos->hwnd, GA_PARENT ) == GetDesktopWindow()) - winpos->hwndInsertAfter = SWP_DoOwnedPopups( winpos->hwnd, winpos->hwndInsertAfter ); - } - - /* Common operations */ - - SWP_DoNCCalcSize( winpos, &old_window_rect, &old_client_rect, - &new_window_rect, &new_client_rect, valid_rects, parent_x, parent_y ); - - if (!set_window_pos( winpos->hwnd, winpos->hwndInsertAfter, winpos->flags, - &new_window_rect, &new_client_rect, valid_rects )) - goto done; - - - if( winpos->flags & SWP_HIDEWINDOW ) - HideCaret(winpos->hwnd); - else if (winpos->flags & SWP_SHOWWINDOW) - ShowCaret(winpos->hwnd); - - if (!(winpos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) - { - /* child windows get WM_CHILDACTIVATE message */ - if ((GetWindowLongW( winpos->hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD) - SendMessageW( winpos->hwnd, WM_CHILDACTIVATE, 0, 0 ); - else - SetForegroundWindow( winpos->hwnd ); - } - - if(!(orig_flags & SWP_DEFERERASE)) - { - /* erase parent when hiding or resizing child */ - if ((orig_flags & SWP_HIDEWINDOW) || - (!(orig_flags & SWP_SHOWWINDOW) && - (winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE)) - { - HWND parent = NtUserGetAncestor( winpos->hwnd, GA_PARENT ); - if (!parent || parent == GetDesktopWindow()) parent = winpos->hwnd; - erase_now( parent, 0 ); - } - - /* Give newly shown windows a chance to redraw */ - if(((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) - && !(orig_flags & SWP_AGG_NOCLIENTCHANGE) && (orig_flags & SWP_SHOWWINDOW)) - { - erase_now(winpos->hwnd, 0); - } - } - - /* And last, send the WM_WINDOWPOSCHANGED message */ - - TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS); - - if (((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) - && !((orig_flags & SWP_AGG_NOCLIENTCHANGE) && (orig_flags & SWP_SHOWWINDOW))) - { - /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set - and always contains final window position. - */ - winpos->x = new_window_rect.left; - winpos->y = new_window_rect.top; - winpos->cx = new_window_rect.right - new_window_rect.left; - winpos->cy = new_window_rect.bottom - new_window_rect.top; - SendMessageW( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos ); - } - ret = TRUE; -done: - SetThreadDpiAwarenessContext( context ); - return ret; -} - /*********************************************************************** * BeginDeferWindowPos (USER32.@) */ diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 5499744482a..56fce1c6496 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1194,6 +1194,7 @@ static const struct user_driver_funcs lazy_load_driver = .pGetDC = loaderdrv_GetDC, .pSetCapture = nulldrv_SetCapture, .pSetLayeredWindowAttributes = loaderdrv_SetLayeredWindowAttributes, + .pSetParent = nulldrv_SetParent, .pSetWindowRgn = loaderdrv_SetWindowRgn, .pMsgWaitForMultipleObjectsEx = nulldrv_MsgWaitForMultipleObjectsEx, .pReleaseDC = nulldrv_ReleaseDC, diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 6c8e29ca1ba..b8d12a23dd3 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1200,6 +1200,7 @@ static struct unix_funcs unix_funcs = NtUserSetCursorPos, NtUserSetFocus, NtUserSetLayeredWindowAttributes, + NtUserSetParent, NtUserSetSysColors, NtUserSetWindowPos, NtUserSetWindowRgn, diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index e50d406e3d5..5582f627166 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -44,6 +44,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_SETPARENT: + if (is_desktop_window( hwnd )) return 0; + return HandleToUlong( NtUserSetParent( hwnd, UlongToHandle(wparam) )); case WM_WINE_SETACTIVEWINDOW: if (!wparam && NtUserGetForegroundWindow() == hwnd) return 0; return (LRESULT)NtUserSetActiveWindow( (HWND)wparam ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index a9ead8238a4..5452b5126d8 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -37,6 +37,7 @@ 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 *notify_ime)( HWND hwnd, UINT param ); void (CDECL *register_builtin_classes)(void); diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 630f1e362e9..1853e141083 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1214,7 +1214,7 @@ @ stub NtUserSetMonitorWorkArea @ stub NtUserSetMouseInputRateLimitingTimer @ stdcall -syscall NtUserSetObjectInformation(long long ptr long) -@ stub NtUserSetParent +@ stdcall NtUserSetParent(long long) @ stub NtUserSetPrecisionTouchPadConfiguration @ stdcall -syscall NtUserSetProcessDpiAwarenessContext(long long) @ stub NtUserSetProcessInteractionFlags diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 57ebdcb43bd..f956abe2093 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -248,6 +248,7 @@ struct unix_funcs BOOL (WINAPI *pNtUserSetCursorPos)( INT x, INT y ); HWND (WINAPI *pNtUserSetFocus)( HWND hwnd ); BOOL (WINAPI *pNtUserSetLayeredWindowAttributes)( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ); + HWND (WINAPI *pNtUserSetParent)( HWND hwnd, HWND parent ); BOOL (WINAPI *pNtUserSetSysColors)( INT count, const INT *colors, const COLORREF *values ); BOOL (WINAPI *pNtUserSetWindowPos)( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags ); int (WINAPI *pNtUserSetWindowRgn)( HWND hwnd, HRGN hrgn, BOOL redraw ); @@ -340,6 +341,7 @@ extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN; struct tagWND; extern HDWP begin_defer_window_pos( INT count ) 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; extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN; extern DPI_AWARENESS_CONTEXT get_window_dpi_awareness_context( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 11f0b0630f2..42f2d82ddff 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -381,6 +381,103 @@ static HWND get_parent( HWND hwnd ) return retval; } +/***************************************************************** + * NtUserSetParent (win32u.@) + */ +HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent ) +{ + RECT window_rect, old_screen_rect, new_screen_rect; + DPI_AWARENESS_CONTEXT context; + WINDOWPOS winpos; + HWND full_handle; + HWND old_parent = 0; + BOOL was_visible; + WND *win; + BOOL ret; + + TRACE("(%p %p)\n", hwnd, parent); + + if (is_broadcast(hwnd) || is_broadcast(parent)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!parent) parent = get_desktop_window(); + else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent(); + else parent = get_full_window_handle( parent ); + + if (!is_window( parent )) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + + /* Some applications try to set a child as a parent */ + if (is_child( hwnd, parent )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + if (!(full_handle = is_current_thread_window( hwnd ))) + return UlongToHandle( send_message( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 )); + + if (full_handle == parent) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + /* Windows hides the window first, then shows it again + * including the WM_SHOWWINDOW messages and all */ + was_visible = NtUserShowWindow( hwnd, SW_HIDE ); + + win = get_win_ptr( hwnd ); + if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP) return 0; + + get_window_rects( hwnd, COORDS_PARENT, &window_rect, NULL, get_dpi_for_window(hwnd) ); + get_window_rects( hwnd, COORDS_SCREEN, &old_screen_rect, NULL, 0 ); + + SERVER_START_REQ( set_parent ) + { + req->handle = wine_server_user_handle( hwnd ); + req->parent = wine_server_user_handle( parent ); + if ((ret = !wine_server_call_err( req ))) + { + old_parent = wine_server_ptr_handle( reply->old_parent ); + win->parent = parent = wine_server_ptr_handle( reply->full_parent ); + win->dpi = reply->dpi; + win->dpi_awareness = reply->awareness; + } + + } + SERVER_END_REQ; + release_win_ptr( win ); + if (!ret) return 0; + + get_window_rects( hwnd, COORDS_SCREEN, &new_screen_rect, NULL, 0 ); + context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd )); + + user_driver->pSetParent( full_handle, parent, old_parent ); + + winpos.hwnd = hwnd; + winpos.hwndInsertAfter = HWND_TOP; + winpos.x = window_rect.left; + winpos.y = window_rect.top; + winpos.cx = 0; + winpos.cy = 0; + winpos.flags = SWP_NOSIZE; + + set_window_pos( &winpos, new_screen_rect.left - old_screen_rect.left, + new_screen_rect.top - old_screen_rect.top ); + + if (was_visible) NtUserShowWindow( hwnd, SW_SHOW ); + + set_thread_dpi_awareness_context( context ); + return old_parent; +} + /* see GetWindow */ static HWND get_window_relative( HWND hwnd, UINT rel ) { @@ -740,7 +837,7 @@ DPI_AWARENESS_CONTEXT get_window_dpi_awareness_context( HWND hwnd ) } /* see GetDpiForWindow */ -static UINT get_dpi_for_window( HWND hwnd ) +UINT get_dpi_for_window( HWND hwnd ) { WND *win; UINT ret = 0; @@ -1690,6 +1787,14 @@ 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.@) */ diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index d80b519c310..2f9ffd3df40 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1015,6 +1015,12 @@ BOOL WINAPI NtUserSetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alph return unix_funcs->pNtUserSetLayeredWindowAttributes( hwnd, key, alpha, flags ); } +HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent ) +{ + if (!unix_funcs) return 0; + return unix_funcs->pNtUserSetParent( hwnd, parent ); +} + BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *values ) { if (!unix_funcs) return FALSE; diff --git a/include/ntuser.h b/include/ntuser.h index 441d8e836da..dc0517bc767 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -393,6 +393,7 @@ BOOL WINAPI NtUserSetCursorPos( INT x, INT y ); HWND WINAPI NtUserSetFocus( HWND hwnd ); BOOL WINAPI NtUserSetKeyboardState( BYTE *state ); BOOL WINAPI NtUserSetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ); +HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent ); BOOL WINAPI NtUserSetProcessDpiAwarenessContext( ULONG awareness, ULONG unknown ); BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle ); BOOL WINAPI NtUserSetProp( HWND hwnd, const WCHAR *str, HANDLE handle ); @@ -406,6 +407,7 @@ HWINEVENTHOOK WINAPI NtUserSetWinEventHook( DWORD event_min, DWORD event_max, HM UNICODE_STRING *module, WINEVENTPROC proc, DWORD pid, DWORD tid, DWORD flags ); INT WINAPI NtUserShowCursor( BOOL show ); +BOOL WINAPI NtUserShowWindow( 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,