win32u: Move NtUserGetUpdateRect 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:28:20 +01:00 committed by Alexandre Julliard
parent 0c752feda6
commit 1df20bb22a
9 changed files with 74 additions and 234 deletions

View file

@ -47,22 +47,6 @@ void free_dce( struct dce *dce, HWND hwnd )
}
/***********************************************************************
* delete_clip_rgn
*/
static void delete_clip_rgn( struct dce *dce )
{
if (!dce->clip_rgn) return; /* nothing to do */
dce->flags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN);
DeleteObject( dce->clip_rgn );
dce->clip_rgn = 0;
/* make it dirty so that the vis rgn gets recomputed next time */
SetHookFlags( dce->hdc, DCHF_INVALIDATEVISRGN );
}
/***********************************************************************
* invalidate_dce
*
@ -79,36 +63,6 @@ void invalidate_dce( WND *win, const RECT *extra_rect )
}
/***********************************************************************
* release_dc
*
* Implementation of ReleaseDC.
*/
static INT release_dc( HWND hwnd, HDC hdc, BOOL end_paint )
{
struct dce *dce;
BOOL ret = FALSE;
TRACE("%p %p\n", hwnd, hdc );
USER_Lock();
dce = (struct dce *)GetDCHook( hdc, NULL );
if (dce && dce->count && dce->hwnd)
{
if (!(dce->flags & DCX_NORESETATTRS)) SetHookFlags( dce->hdc, DCHF_RESETDC );
if (end_paint || (dce->flags & DCX_CACHE)) delete_clip_rgn( dce );
if (dce->flags & DCX_CACHE)
{
dce->count = 0;
SetHookFlags( dce->hdc, DCHF_DISABLEDC );
}
ret = TRUE;
}
USER_Unlock();
return ret;
}
/***********************************************************************
* get_update_region
*
@ -157,140 +111,6 @@ static HRGN get_update_region( HWND hwnd, UINT *flags, HWND *child )
}
/***********************************************************************
* get_update_flags
*
* Get only the update flags, not the update region.
*/
static BOOL get_update_flags( HWND hwnd, HWND *child, UINT *flags )
{
BOOL ret;
SERVER_START_REQ( get_update_region )
{
req->window = wine_server_user_handle( hwnd );
req->from_child = wine_server_user_handle( child ? *child : 0 );
req->flags = *flags | UPDATE_NOREGION;
if ((ret = !wine_server_call_err( req )))
{
if (child) *child = wine_server_ptr_handle( reply->child );
*flags = reply->flags;
}
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* send_ncpaint
*
* Send a WM_NCPAINT message if needed, and return the resulting update region (in screen coords).
* Helper for erase_now and BeginPaint.
*/
static HRGN send_ncpaint( HWND hwnd, HWND *child, UINT *flags )
{
HRGN whole_rgn = get_update_region( hwnd, flags, child );
HRGN client_rgn = 0;
DWORD style;
if (child) hwnd = *child;
if (hwnd == GetDesktopWindow()) return whole_rgn;
if (whole_rgn)
{
DPI_AWARENESS_CONTEXT context;
RECT client, window, update;
INT type;
context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
/* check if update rgn overlaps with nonclient area */
type = GetRgnBox( whole_rgn, &update );
WIN_GetRectangles( hwnd, COORDS_SCREEN, &window, &client );
if ((*flags & UPDATE_NONCLIENT) ||
update.left < client.left || update.top < client.top ||
update.right > client.right || update.bottom > client.bottom)
{
client_rgn = CreateRectRgnIndirect( &client );
CombineRgn( client_rgn, client_rgn, whole_rgn, RGN_AND );
/* check if update rgn contains complete nonclient area */
if (type == SIMPLEREGION && EqualRect( &window, &update ))
{
DeleteObject( whole_rgn );
whole_rgn = (HRGN)1;
}
}
else
{
client_rgn = whole_rgn;
whole_rgn = 0;
}
if (whole_rgn) /* NOTE: WM_NCPAINT allows wParam to be 1 */
{
if (*flags & UPDATE_NONCLIENT)
{
/* Mark standard scroll bars as not painted before sending WM_NCPAINT */
style = GetWindowLongW( hwnd, GWL_STYLE );
if (style & WS_HSCROLL)
SCROLL_SetStandardScrollPainted( hwnd, SB_HORZ, FALSE );
if (style & WS_VSCROLL)
SCROLL_SetStandardScrollPainted( hwnd, SB_VERT, FALSE );
SendMessageW( hwnd, WM_NCPAINT, (WPARAM)whole_rgn, 0 );
}
if (whole_rgn > (HRGN)1) DeleteObject( whole_rgn );
}
SetThreadDpiAwarenessContext( context );
}
return client_rgn;
}
/***********************************************************************
* send_erase
*
* Send a WM_ERASEBKGND message if needed, and optionally return the DC for painting.
* If a DC is requested, the region is selected into it. In all cases the region is deleted.
* Helper for erase_now and BeginPaint.
*/
static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn,
RECT *clip_rect, HDC *hdc_ret )
{
BOOL need_erase = (flags & UPDATE_DELAYED_ERASE) != 0;
HDC hdc = 0;
RECT dummy;
if (!clip_rect) clip_rect = &dummy;
if (hdc_ret || (flags & UPDATE_ERASE))
{
UINT dcx_flags = DCX_INTERSECTRGN | DCX_USESTYLE;
if (IsIconic(hwnd)) dcx_flags |= DCX_WINDOW;
if ((hdc = NtUserGetDCEx( hwnd, client_rgn, dcx_flags )))
{
INT type = GetClipBox( hdc, clip_rect );
if (flags & UPDATE_ERASE)
{
/* don't erase if the clip box is empty */
if (type != NULLREGION)
need_erase = !SendMessageW( hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0 );
}
if (!hdc_ret) release_dc( hwnd, hdc, TRUE );
}
if (hdc_ret) *hdc_ret = hdc;
}
if (!hdc) DeleteObject( client_rgn );
return need_erase;
}
/***********************************************************************
* copy_bits_from_surface
*
@ -582,44 +402,6 @@ BOOL WINAPI ValidateRect( HWND hwnd, const RECT *rect )
}
/***********************************************************************
* GetUpdateRect (USER32.@)
*/
BOOL WINAPI GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
{
DPI_AWARENESS_CONTEXT context;
UINT flags = UPDATE_NOCHILDREN;
HRGN update_rgn;
BOOL need_erase;
if (erase) flags |= UPDATE_NONCLIENT | UPDATE_ERASE;
if (!(update_rgn = send_ncpaint( hwnd, NULL, &flags ))) return FALSE;
if (rect)
{
if (GetRgnBox( update_rgn, rect ) != NULLREGION)
{
HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE );
DWORD layout = SetLayout( hdc, 0 ); /* MapWindowPoints mirrors already */
context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
MapWindowPoints( 0, hwnd, (LPPOINT)rect, 2 );
SetThreadDpiAwarenessContext( context );
*rect = rect_win_to_thread_dpi( hwnd, *rect );
DPtoLP( hdc, (LPPOINT)rect, 2 );
SetLayout( hdc, layout );
NtUserReleaseDC( hwnd, hdc );
}
}
need_erase = send_erase( hwnd, flags, update_rgn, NULL, NULL );
/* check if we still have an update region */
flags = UPDATE_PAINT | UPDATE_NOCHILDREN;
if (need_erase) flags |= UPDATE_DELAYED_ERASE;
return (get_update_flags( hwnd, NULL, &flags ) && (flags & UPDATE_PAINT));
}
/***********************************************************************
* ExcludeUpdateRgn (USER32.@)
*/

View file

@ -392,7 +392,7 @@
@ stdcall GetTitleBarInfo(long ptr)
@ stdcall GetTopWindow(long)
@ stdcall GetTouchInputInfo(long long ptr long)
@ stdcall GetUpdateRect(long ptr long)
@ stdcall GetUpdateRect(long ptr long) NtUserGetUpdateRect
@ stdcall GetUpdateRgn(long long long) NtUserGetUpdateRgn
@ stdcall GetUpdatedClipboardFormats(ptr long ptr) NtUserGetUpdatedClipboardFormats
@ stdcall GetUserObjectInformationA (long long ptr long ptr)

View file

@ -1167,3 +1167,35 @@ INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
set_thread_dpi_awareness_context( context );
return retval;
}
/***********************************************************************
* NtUserGetUpdateRect (win32u.@)
*/
BOOL WINAPI NtUserGetUpdateRect( HWND hwnd, RECT *rect, BOOL erase )
{
UINT flags = UPDATE_NOCHILDREN;
HRGN update_rgn;
BOOL need_erase;
if (erase) flags |= UPDATE_NONCLIENT | UPDATE_ERASE;
if (!(update_rgn = send_ncpaint( hwnd, NULL, &flags ))) return FALSE;
if (rect && NtGdiGetRgnBox( update_rgn, rect ) != NULLREGION)
{
HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE );
DWORD layout = NtGdiSetLayout( hdc, -1, 0 ); /* map_window_points mirrors already */
UINT win_dpi = get_dpi_for_window( hwnd );
map_window_points( 0, hwnd, (POINT *)rect, 2, win_dpi );
*rect = map_dpi_rect( *rect, win_dpi, get_thread_dpi() );
NtGdiTransformPoints( hdc, (POINT *)rect, (POINT *)rect, 2, NtGdiDPtoLP );
NtGdiSetLayout( hdc, -1, layout );
NtUserReleaseDC( hwnd, hdc );
}
need_erase = send_erase( hwnd, flags, update_rgn, NULL, NULL );
/* check if we still have an update region */
flags = UPDATE_PAINT | UPDATE_NOCHILDREN;
if (need_erase) flags |= UPDATE_DELAYED_ERASE;
return get_update_flags( hwnd, NULL, &flags ) && (flags & UPDATE_PAINT);
}

View file

@ -1179,6 +1179,7 @@ static struct unix_funcs unix_funcs =
NtUserGetKeyboardLayoutList,
NtUserGetPriorityClipboardFormat,
NtUserGetQueueStatus,
NtUserGetUpdateRect,
NtUserGetUpdateRgn,
NtUserGetUpdatedClipboardFormats,
NtUserIsClipboardFormatAvailable,
@ -1214,7 +1215,6 @@ static struct unix_funcs unix_funcs =
NtUserVkKeyScanEx,
NtUserWindowFromPoint,
GetDCHook,
SetDIBits,
SetHookFlags,
__wine_get_brush_bitmap_info,

View file

@ -1002,7 +1002,7 @@
@ stub NtUserGetTouchInputInfo
@ stub NtUserGetTouchValidationStatus
@ stub NtUserGetUniformSpaceMapping
@ stub NtUserGetUpdateRect
@ stdcall NtUserGetUpdateRect(long ptr long)
@ stdcall NtUserGetUpdateRgn(long long long)
@ stdcall NtUserGetUpdatedClipboardFormats(ptr long ptr)
@ stub NtUserGetWOWClass
@ -1321,7 +1321,6 @@
# Wine internal extensions
# user32
@ stdcall GetDCHook(long ptr)
@ stdcall SetHookFlags(long long)
@ cdecl __wine_set_visible_region(long long ptr ptr ptr)

View file

@ -222,6 +222,7 @@ struct unix_funcs
UINT (WINAPI *pNtUserGetKeyboardLayoutList)( INT size, HKL *layouts );
INT (WINAPI *pNtUserGetPriorityClipboardFormat)( UINT *list, INT count );
DWORD (WINAPI *pNtUserGetQueueStatus)( UINT flags );
BOOL (WINAPI *pNtUserGetUpdateRect)( HWND hwnd, RECT *rect, BOOL erase );
INT (WINAPI *pNtUserGetUpdateRgn)( HWND hwnd, HRGN hrgn, BOOL erase );
BOOL (WINAPI *pNtUserGetUpdatedClipboardFormats)( UINT *formats, UINT size, UINT *out_size );
BOOL (WINAPI *pNtUserIsClipboardFormatAvailable)( UINT format );
@ -269,7 +270,6 @@ struct unix_funcs
HWND (WINAPI *pNtUserWindowFromPoint)( LONG x, LONG y );
/* Wine-specific functions */
DWORD_PTR (WINAPI *pGetDCHook)( HDC hdc, DCHOOKPROC *proc );
INT (WINAPI *pSetDIBits)( HDC hdc, HBITMAP hbitmap, UINT startscan,
UINT lines, const void *bits, const BITMAPINFO *info,
UINT coloruse );
@ -358,6 +358,8 @@ 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 int map_window_points( HWND hwnd_from, HWND hwnd_to, POINT *points, UINT count,
UINT dpi ) DECLSPEC_HIDDEN;
extern void map_window_region( HWND from, HWND to, HRGN hrgn ) DECLSPEC_HIDDEN;
extern BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ) DECLSPEC_HIDDEN;
extern void update_window_state( HWND hwnd ) DECLSPEC_HIDDEN;

View file

@ -1873,7 +1873,7 @@ INT WINAPI NtUserInternalGetWindowText( HWND hwnd, WCHAR *text, INT count )
* 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 )
static BOOL get_windows_offset( HWND hwnd_from, HWND hwnd_to, UINT dpi, BOOL *mirrored, POINT *ret_offset )
{
WND *win;
POINT offset;
@ -1915,7 +1915,7 @@ static BOOL get_windows_offset( HWND hwnd_from, HWND hwnd_to, BOOL *mirrored, PO
}
}
if (win && win != WND_DESKTOP) release_win_ptr( win );
offset = map_dpi_point( offset, get_dpi_for_window( hwnd_from ), get_thread_dpi() );
offset = map_dpi_point( offset, get_dpi_for_window( hwnd_from ), dpi );
}
}
@ -1952,7 +1952,7 @@ static BOOL get_windows_offset( HWND hwnd_from, HWND hwnd_to, BOOL *mirrored, PO
}
}
if (win && win != WND_DESKTOP) release_win_ptr( win );
pt = map_dpi_point( pt, get_dpi_for_window( hwnd_to ), get_thread_dpi() );
pt = map_dpi_point( pt, get_dpi_for_window( hwnd_to ), dpi );
offset.x -= pt.x;
offset.y -= pt.y;
}
@ -1968,7 +1968,7 @@ other_process: /* one of the parents may belong to another process, do it the h
{
req->from = wine_server_user_handle( hwnd_from );
req->to = wine_server_user_handle( hwnd_to );
req->dpi = get_thread_dpi();
req->dpi = dpi;
if ((ret = !wine_server_call_err( req )))
{
ret_offset->x = reply->x;
@ -1990,7 +1990,7 @@ void map_window_region( HWND from, HWND to, HRGN hrgn )
HRGN new_rgn;
RECT *rect;
if (!get_windows_offset( from, to, &mirrored, &offset )) return;
if (!get_windows_offset( from, to, get_thread_dpi(), &mirrored, &offset )) return;
if (!mirrored)
{
@ -2017,6 +2017,30 @@ void map_window_region( HWND from, HWND to, HRGN hrgn )
free( data );
}
/* see MapWindowPoints */
int map_window_points( HWND hwnd_from, HWND hwnd_to, POINT *points, UINT count, UINT dpi )
{
BOOL mirrored;
POINT offset;
UINT i;
if (!get_windows_offset( hwnd_from, hwnd_to, dpi, &mirrored, &offset )) return 0;
for (i = 0; i < count; i++)
{
points[i].x += offset.x;
points[i].y += offset.y;
if (mirrored) points[i].x = -points[i].x;
}
if (mirrored && count == 2) /* special case for rectangle */
{
int tmp = points[0].x;
points[0].x = points[1].x;
points[1].x = tmp;
}
return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
}
/***********************************************************************
* dump_winpos_flags
*/

View file

@ -873,6 +873,12 @@ INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size )
return unix_funcs->pNtUserGetKeyNameText( lparam, buffer, size );
}
BOOL WINAPI NtUserGetUpdateRect( HWND hwnd, RECT *rect, BOOL erase )
{
if (!unix_funcs) return FALSE;
return unix_funcs->pNtUserGetUpdateRect( hwnd, rect, erase );
}
INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
{
if (!unix_funcs) return 0;
@ -1098,12 +1104,6 @@ HWND WINAPI NtUserWindowFromPoint( LONG x, LONG y )
return unix_funcs->pNtUserWindowFromPoint( x, y );
}
DWORD_PTR WINAPI GetDCHook( HDC hdc, DCHOOKPROC *proc )
{
if (!unix_funcs) return 0;
return unix_funcs->pGetDCHook( hdc, proc );
}
INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
UINT lines, const void *bits, const BITMAPINFO *info,
UINT coloruse )

View file

@ -355,6 +355,7 @@ 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 );
BOOL WINAPI NtUserGetUpdateRect( HWND hwnd, RECT *rect, BOOL erase );
int WINAPI NtUserGetWindowRgnEx( HWND hwnd, HRGN hrgn, UINT unk );
NTSTATUS WINAPI NtUserInitializeClientPfnArrays( const struct user_client_procs *client_procsA,
const struct user_client_procs *client_procsW,