win32u: Move NtUserGetUpdateRgn 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-14 11:45:43 +01:00 committed by Alexandre Julliard
parent 45e0afbca4
commit d942281a00
12 changed files with 197 additions and 76 deletions

View file

@ -3943,7 +3943,7 @@ LRESULT WINAPI DECLSPEC_HOTPATCH DispatchMessageA( const MSG* msg )
{
/* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
GetUpdateRgn( msg->hwnd, hrgn, TRUE );
NtUserGetUpdateRgn( msg->hwnd, hrgn, TRUE );
DeleteObject( hrgn );
}
return retval;
@ -4014,7 +4014,7 @@ LRESULT WINAPI DECLSPEC_HOTPATCH DispatchMessageW( const MSG* msg )
{
/* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
GetUpdateRgn( msg->hwnd, hrgn, TRUE );
NtUserGetUpdateRgn( msg->hwnd, hrgn, TRUE );
DeleteObject( hrgn );
}
return retval;

View file

@ -611,36 +611,6 @@ BOOL WINAPI ValidateRect( HWND hwnd, const RECT *rect )
}
/***********************************************************************
* GetUpdateRgn (USER32.@)
*/
INT WINAPI GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
{
DPI_AWARENESS_CONTEXT context;
INT retval = ERROR;
UINT flags = UPDATE_NOCHILDREN;
HRGN update_rgn;
context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
if (erase) flags |= UPDATE_NONCLIENT | UPDATE_ERASE;
if ((update_rgn = send_ncpaint( hwnd, NULL, &flags )))
{
retval = CombineRgn( hrgn, update_rgn, 0, RGN_COPY );
if (send_erase( hwnd, flags, update_rgn, NULL, NULL ))
{
flags = UPDATE_DELAYED_ERASE;
get_update_flags( hwnd, NULL, &flags );
}
/* map region to client coordinates */
map_window_region( 0, hwnd, hrgn );
}
SetThreadDpiAwarenessContext( context );
return retval;
}
/***********************************************************************
* GetUpdateRect (USER32.@)
*/
@ -685,7 +655,7 @@ BOOL WINAPI GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
INT WINAPI ExcludeUpdateRgn( HDC hdc, HWND hwnd )
{
HRGN update_rgn = CreateRectRgn( 0, 0, 0, 0 );
INT ret = GetUpdateRgn( hwnd, update_rgn, FALSE );
INT ret = NtUserGetUpdateRgn( hwnd, update_rgn, FALSE );
if (ret != ERROR)
{
@ -772,7 +742,7 @@ static INT scroll_window( HWND hwnd, INT dx, INT dy, const RECT *rect, const REC
* scrolled as well. Keep a copy in hrgnWinupd
* to be added to hrngUpdate at the end. */
hrgnTemp = CreateRectRgn( 0, 0, 0, 0 );
retVal = GetUpdateRgn( hwnd, hrgnTemp, FALSE );
retVal = NtUserGetUpdateRgn( hwnd, hrgnTemp, FALSE );
if (retVal != NULLREGION)
{
HRGN hrgnClip = CreateRectRgnIndirect(&cliprc);

View file

@ -393,7 +393,7 @@
@ stdcall GetTopWindow(long)
@ stdcall GetTouchInputInfo(long long ptr long)
@ stdcall GetUpdateRect(long ptr long)
@ stdcall GetUpdateRgn(long long long)
@ stdcall GetUpdateRgn(long long long) NtUserGetUpdateRgn
@ stdcall GetUpdatedClipboardFormats(ptr long ptr) NtUserGetUpdatedClipboardFormats
@ stdcall GetUserObjectInformationA (long long ptr long ptr)
@ stdcall GetUserObjectInformationW (long long ptr long ptr) NtUserGetObjectInformation

View file

@ -45,7 +45,6 @@ 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 void map_window_region( HWND from, HWND to, HRGN hrgn ) DECLSPEC_HIDDEN;
extern LRESULT WIN_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN;
extern void destroy_thread_windows(void) DECLSPEC_HIDDEN;
extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;

View file

@ -404,43 +404,6 @@ static BOOL WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, BOOL *mirrored, POI
return ret;
}
/* map coordinates of a window region */
void map_window_region( HWND from, HWND to, HRGN hrgn )
{
BOOL mirrored;
POINT offset;
UINT i, size;
RGNDATA *data;
HRGN new_rgn;
RECT *rect;
if (!WINPOS_GetWinOffset( from, to, &mirrored, &offset )) return;
if (!mirrored)
{
OffsetRgn( hrgn, offset.x, offset.y );
return;
}
if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
GetRegionData( hrgn, size, data );
rect = (RECT *)data->Buffer;
for (i = 0; i < data->rdh.nCount; i++)
{
int tmp = -(rect[i].left + offset.x);
rect[i].left = -(rect[i].right + offset.x);
rect[i].right = tmp;
rect[i].top += offset.y;
rect[i].bottom += offset.y;
}
if ((new_rgn = ExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data )))
{
CombineRgn( hrgn, new_rgn, 0, RGN_COPY );
DeleteObject( new_rgn );
}
HeapFree( GetProcessHeap(), 0, data );
}
/*******************************************************************
* MapWindowPoints (USER32.@)

View file

@ -548,7 +548,7 @@ void invalidate_dce( WND *win, const RECT *extra_rect )
if (!win->parent) return;
context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( win->obj.handle ));
get_window_rects( win->obj.handle, COORDS_SCREEN, &window_rect, NULL, get_thread_dpi() );
get_window_rect( win->obj.handle, &window_rect, get_thread_dpi() );
TRACE("%p parent %p %s (%s)\n",
win->obj.handle, win->parent, wine_dbgstr_rect(&window_rect), wine_dbgstr_rect(extra_rect) );
@ -576,7 +576,7 @@ void invalidate_dce( WND *win, const RECT *extra_rect )
if (win->parent == dce->hwnd || is_child( win->parent, dce->hwnd ))
{
RECT dce_rect, tmp;
get_window_rects( dce->hwnd, COORDS_SCREEN, &dce_rect, NULL, get_thread_dpi() );
get_window_rect( dce->hwnd, &dce_rect, get_thread_dpi() );
if (intersect_rect( &tmp, &dce_rect, &window_rect ) ||
(extra_rect && intersect_rect( &tmp, &dce_rect, extra_rect )))
make_dc_dirty( dce );
@ -1138,3 +1138,32 @@ BOOL WINAPI NtUserRedrawWindow( HWND hwnd, const RECT *rect, HRGN hrgn, UINT fla
return ret;
}
/***********************************************************************
* NtUserGetUpdateRgn (win32u.@)
*/
INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
{
DPI_AWARENESS_CONTEXT context;
INT retval = ERROR;
UINT flags = UPDATE_NOCHILDREN;
HRGN update_rgn;
context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd ));
if (erase) flags |= UPDATE_NONCLIENT | UPDATE_ERASE;
if ((update_rgn = send_ncpaint( hwnd, NULL, &flags )))
{
retval = NtGdiCombineRgn( hrgn, update_rgn, 0, RGN_COPY );
if (send_erase( hwnd, flags, update_rgn, NULL, NULL ))
{
flags = UPDATE_DELAYED_ERASE;
get_update_flags( hwnd, NULL, &flags );
}
/* map region to client coordinates */
map_window_region( 0, hwnd, hrgn );
}
set_thread_dpi_awareness_context( context );
return retval;
}

View file

@ -1177,6 +1177,7 @@ static struct unix_funcs unix_funcs =
NtUserGetKeyboardLayoutList,
NtUserGetPriorityClipboardFormat,
NtUserGetQueueStatus,
NtUserGetUpdateRgn,
NtUserGetUpdatedClipboardFormats,
NtUserIsClipboardFormatAvailable,
NtUserMapVirtualKeyEx,

View file

@ -1003,7 +1003,7 @@
@ stub NtUserGetTouchValidationStatus
@ stub NtUserGetUniformSpaceMapping
@ stub NtUserGetUpdateRect
@ stub NtUserGetUpdateRgn
@ stdcall NtUserGetUpdateRgn(long long long)
@ stdcall NtUserGetUpdatedClipboardFormats(ptr long ptr)
@ stub NtUserGetWOWClass
@ stub NtUserGetWindowBand

View file

@ -218,6 +218,7 @@ struct unix_funcs
UINT (WINAPI *pNtUserGetKeyboardLayoutList)( INT size, HKL *layouts );
INT (WINAPI *pNtUserGetPriorityClipboardFormat)( UINT *list, INT count );
DWORD (WINAPI *pNtUserGetQueueStatus)( UINT flags );
INT (WINAPI *pNtUserGetUpdateRgn)( HWND hwnd, HRGN hrgn, BOOL erase );
BOOL (WINAPI *pNtUserGetUpdatedClipboardFormats)( UINT *formats, UINT size, UINT *out_size );
BOOL (WINAPI *pNtUserIsClipboardFormatAvailable)( UINT format );
UINT (WINAPI *pNtUserMapVirtualKeyEx)( UINT code, UINT type, HKL layout );
@ -346,6 +347,7 @@ extern BOOL get_window_rects( HWND hwnd, enum coords_relative relative, RECT *wi
RECT *client_rect, UINT dpi ) DECLSPEC_HIDDEN;
extern HWND *list_window_children( HDESK desktop, HWND hwnd, UNICODE_STRING *class,
DWORD tid ) DECLSPEC_HIDDEN;
extern void map_window_region( HWND from, HWND to, HRGN hrgn ) DECLSPEC_HIDDEN;
extern void update_window_state( HWND hwnd ) DECLSPEC_HIDDEN;
/* to release pointers retrieved by win_get_ptr */

View file

@ -1762,6 +1762,156 @@ INT WINAPI NtUserInternalGetWindowText( HWND hwnd, WCHAR *text, INT count )
return lstrlenW(text);
}
/*******************************************************************
* get_windows_offset
*
* Calculate the offset between the origin of the two windows. Used
* to implement MapWindowPoints.
*/
static BOOL get_windows_offset( HWND hwnd_from, HWND hwnd_to, BOOL *mirrored, POINT *ret_offset )
{
WND *win;
POINT offset;
BOOL mirror_from, mirror_to, ret;
HWND hwnd;
offset.x = offset.y = 0;
*mirrored = mirror_from = mirror_to = FALSE;
/* Translate source window origin to screen coords */
if (hwnd_from)
{
if (!(win = get_win_ptr( hwnd_from )))
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return FALSE;
}
if (win == WND_OTHER_PROCESS) goto other_process;
if (win != WND_DESKTOP)
{
if (win->dwExStyle & WS_EX_LAYOUTRTL)
{
mirror_from = TRUE;
offset.x += win->client_rect.right - win->client_rect.left;
}
while (win->parent)
{
offset.x += win->client_rect.left;
offset.y += win->client_rect.top;
hwnd = win->parent;
release_win_ptr( win );
if (!(win = get_win_ptr( hwnd ))) break;
if (win == WND_OTHER_PROCESS) goto other_process;
if (win == WND_DESKTOP) break;
if (win->flags & WIN_CHILDREN_MOVED)
{
release_win_ptr( win );
goto other_process;
}
}
if (win && win != WND_DESKTOP) release_win_ptr( win );
offset = map_dpi_point( offset, get_dpi_for_window( hwnd_from ), get_thread_dpi() );
}
}
/* Translate origin to destination window coords */
if (hwnd_to)
{
if (!(win = get_win_ptr( hwnd_to )))
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return FALSE;
}
if (win == WND_OTHER_PROCESS) goto other_process;
if (win != WND_DESKTOP)
{
POINT pt = { 0, 0 };
if (win->dwExStyle & WS_EX_LAYOUTRTL)
{
mirror_to = TRUE;
pt.x += win->client_rect.right - win->client_rect.left;
}
while (win->parent)
{
pt.x += win->client_rect.left;
pt.y += win->client_rect.top;
hwnd = win->parent;
release_win_ptr( win );
if (!(win = get_win_ptr( hwnd ))) break;
if (win == WND_OTHER_PROCESS) goto other_process;
if (win == WND_DESKTOP) break;
if (win->flags & WIN_CHILDREN_MOVED)
{
release_win_ptr( win );
goto other_process;
}
}
if (win && win != WND_DESKTOP) release_win_ptr( win );
pt = map_dpi_point( pt, get_dpi_for_window( hwnd_to ), get_thread_dpi() );
offset.x -= pt.x;
offset.y -= pt.y;
}
}
*mirrored = mirror_from ^ mirror_to;
if (mirror_from) offset.x = -offset.x;
*ret_offset = offset;
return TRUE;
other_process: /* one of the parents may belong to another process, do it the hard way */
SERVER_START_REQ( get_windows_offset )
{
req->from = wine_server_user_handle( hwnd_from );
req->to = wine_server_user_handle( hwnd_to );
req->dpi = get_thread_dpi();
if ((ret = !wine_server_call_err( req )))
{
ret_offset->x = reply->x;
ret_offset->y = reply->y;
*mirrored = reply->mirror;
}
}
SERVER_END_REQ;
return ret;
}
/* map coordinates of a window region */
void map_window_region( HWND from, HWND to, HRGN hrgn )
{
BOOL mirrored;
POINT offset;
UINT i, size;
RGNDATA *data;
HRGN new_rgn;
RECT *rect;
if (!get_windows_offset( from, to, &mirrored, &offset )) return;
if (!mirrored)
{
NtGdiOffsetRgn( hrgn, offset.x, offset.y );
return;
}
if (!(size = NtGdiGetRegionData( hrgn, 0, NULL ))) return;
if (!(data = malloc( size ))) return;
NtGdiGetRegionData( hrgn, size, data );
rect = (RECT *)data->Buffer;
for (i = 0; i < data->rdh.nCount; i++)
{
int tmp = -(rect[i].left + offset.x);
rect[i].left = -(rect[i].right + offset.x);
rect[i].right = tmp;
rect[i].top += offset.y;
rect[i].bottom += offset.y;
}
if ((new_rgn = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data )))
{
NtGdiCombineRgn( hrgn, new_rgn, 0, RGN_COPY );
NtGdiDeleteObjectApp( new_rgn );
}
free( data );
}
/*******************************************************************
* update_window_state
*

View file

@ -858,6 +858,12 @@ INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size )
return unix_funcs->pNtUserGetKeyNameText( lparam, buffer, size );
}
INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
{
if (!unix_funcs) return 0;
return unix_funcs->pNtUserGetUpdateRgn( hwnd, hrgn, erase );
}
BOOL WINAPI NtUserMoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy, BOOL repaint )
{
if (!unix_funcs) return 0;

View file

@ -349,6 +349,7 @@ ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process );
DWORD WINAPI NtUserGetQueueStatus( UINT flags );
ULONG WINAPI NtUserGetSystemDpiForProcess( HANDLE process );
HDESK WINAPI NtUserGetThreadDesktop( DWORD thread );
INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase );
BOOL WINAPI NtUserGetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size );
int WINAPI NtUserGetWindowRgnEx( HWND hwnd, HRGN hrgn, UINT unk );
NTSTATUS WINAPI NtUserInitializeClientPfnArrays( const struct user_client_procs *client_procsA,