win32u: Move NtUserSetParent implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-03-15 14:27:55 +01:00 committed by Alexandre Julliard
parent 5cc5fdfffd
commit 0c752feda6
18 changed files with 128 additions and 655 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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:

View File

@ -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
*

View File

@ -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)

View File

@ -150,6 +150,7 @@ static const struct user_callbacks user_funcs =
SendMessageW,
SendNotifyMessageW,
ShowCaret,
ShowWindow,
WaitForInputIdle,
notify_ime,
register_builtin_classes,

View File

@ -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 );

View File

@ -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.@)
*/

View File

@ -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)&params );
*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.@)
*/

View File

@ -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,

View File

@ -1200,6 +1200,7 @@ static struct unix_funcs unix_funcs =
NtUserSetCursorPos,
NtUserSetFocus,
NtUserSetLayeredWindowAttributes,
NtUserSetParent,
NtUserSetSysColors,
NtUserSetWindowPos,
NtUserSetWindowRgn,

View File

@ -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 );

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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.@)
*/

View File

@ -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;

View File

@ -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,