win32u: Move NtUserScrollDC 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 2021-11-17 12:49:37 +01:00 committed by Alexandre Julliard
parent d60708a17f
commit 5204622efa
11 changed files with 133 additions and 131 deletions

View file

@ -154,15 +154,6 @@ static void CDECL nulldrv_ReleaseDC( HWND hwnd, HDC hdc )
{
}
static BOOL CDECL nulldrv_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update )
{
RECT rect;
GetClipBox( hdc, &rect );
return BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
hdc, rect.left - dx, rect.top - dy, SRCCOPY );
}
static void CDECL nulldrv_SetCapture( HWND hwnd, UINT flags )
{
}
@ -365,7 +356,7 @@ static struct user_driver_funcs lazy_load_driver =
loaderdrv_GetDC,
nulldrv_MsgWaitForMultipleObjectsEx,
nulldrv_ReleaseDC,
nulldrv_ScrollDC,
NULL,
nulldrv_SetCapture,
nulldrv_SetFocus,
loaderdrv_SetLayeredWindowAttributes,

View file

@ -1506,7 +1506,7 @@ static INT scroll_window( HWND hwnd, INT dx, INT dy, const RECT *rect, const REC
hDC = GetDCEx( hwnd, 0, dcxflags);
if (hDC)
{
ScrollDC( hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate );
NtUserScrollDC( hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate );
ReleaseDC( hwnd, hDC );
@ -1632,119 +1632,6 @@ BOOL WINAPI ScrollWindow( HWND hwnd, INT dx, INT dy,
SW_INVALIDATE | SW_ERASE | (rect ? 0 : SW_SCROLLCHILDREN), FALSE ) != ERROR;
}
/*************************************************************************
* ScrollDC (USER32.@)
*
* dx, dy, lprcScroll and lprcClip are all in logical coordinates (msdn is
* wrong) hrgnUpdate is returned in device coordinates with rcUpdate in
* logical coordinates.
*/
BOOL WINAPI ScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, LPRECT update_rect )
{
HRGN update_rgn = ret_update_rgn;
RECT src_rect, clip_rect, offset;
INT dxdev, dydev;
HRGN dstrgn, cliprgn, visrgn;
BOOL ret;
TRACE( "dx,dy %d,%d scroll %s clip %s update %p rect %p\n",
dx, dy, wine_dbgstr_rect(scroll), wine_dbgstr_rect(clip), ret_update_rgn, update_rect );
/* get the visible region */
visrgn = CreateRectRgn( 0, 0, 0, 0 );
GetRandomRgn( hdc, visrgn, SYSRGN );
if (!(GetVersion() & 0x80000000))
{
POINT org;
GetDCOrgEx( hdc, &org );
OffsetRgn( visrgn, -org.x, -org.y );
}
/* intersect with the clipping region if the DC has one */
cliprgn = CreateRectRgn( 0, 0, 0, 0);
if (GetClipRgn( hdc, cliprgn ) != 1)
{
DeleteObject( cliprgn );
cliprgn = 0;
}
else CombineRgn( visrgn, visrgn, cliprgn, RGN_AND );
/* only those pixels in the scroll rectangle that remain in the clipping
* rect are scrolled. */
if (clip)
clip_rect = *clip;
else
GetClipBox( hdc, &clip_rect );
src_rect = clip_rect;
OffsetRect( &clip_rect, -dx, -dy );
IntersectRect( &src_rect, &src_rect, &clip_rect );
/* if an scroll rectangle is specified, only the pixels within that
* rectangle are scrolled */
if (scroll) IntersectRect( &src_rect, &src_rect, scroll );
/* now convert to device coordinates */
LPtoDP( hdc, (LPPOINT)&src_rect, 2 );
TRACE( "source rect: %s\n", wine_dbgstr_rect(&src_rect) );
/* also dx and dy */
SetRect( &offset, 0, 0, dx, dy );
LPtoDP( hdc, (LPPOINT)&offset, 2 );
dxdev = offset.right - offset.left;
dydev = offset.bottom - offset.top;
/* now intersect with the visible region to get the pixels that will actually scroll */
dstrgn = CreateRectRgnIndirect( &src_rect );
CombineRgn( dstrgn, dstrgn, visrgn, RGN_AND );
OffsetRgn( dstrgn, dxdev, dydev );
ExtSelectClipRgn( hdc, dstrgn, RGN_AND );
/* compute the update areas. This is the combined clip rectangle
* minus the scrolled region, and intersected with the visible region. */
if (ret_update_rgn || update_rect)
{
/* intersect clip and scroll rectangles, allowing NULL values */
if (scroll)
{
if (clip)
IntersectRect( &clip_rect, clip, scroll );
else
clip_rect = *scroll;
}
else if (clip)
clip_rect = *clip;
else
GetClipBox( hdc, &clip_rect );
/* Convert the combined clip rectangle to device coordinates */
LPtoDP( hdc, (LPPOINT)&clip_rect, 2 );
if (update_rgn)
SetRectRgn( update_rgn, clip_rect.left, clip_rect.top, clip_rect.right, clip_rect.bottom );
else
update_rgn = CreateRectRgnIndirect( &clip_rect );
CombineRgn( update_rgn, update_rgn, visrgn, RGN_AND );
CombineRgn( update_rgn, update_rgn, dstrgn, RGN_DIFF );
}
ret = USER_Driver->pScrollDC( hdc, dx, dy, update_rgn );
if (ret && update_rect)
{
GetRgnBox( update_rgn, update_rect );
DPtoLP( hdc, (LPPOINT)update_rect, 2 );
TRACE( "returning update_rect %s\n", wine_dbgstr_rect(update_rect) );
}
if (!ret_update_rgn) DeleteObject( update_rgn );
SelectClipRgn( hdc, cliprgn );
if (cliprgn) DeleteObject( cliprgn );
DeleteObject( visrgn );
DeleteObject( dstrgn );
return ret;
}
/************************************************************************
* PrintWindow (USER32.@)
*

View file

@ -627,7 +627,7 @@
@ stdcall ReuseDDElParam(long long long long long)
@ stdcall ScreenToClient(long ptr)
@ stdcall ScrollChildren(long long long long)
@ stdcall ScrollDC(long long long ptr ptr long ptr)
@ stdcall ScrollDC(long long long ptr ptr long ptr) NtUserScrollDC
@ stdcall ScrollWindow(long long long ptr ptr)
@ stdcall ScrollWindowEx(long long long ptr ptr long ptr long)
@ stdcall SendDlgItemMessageA(long long long long long)

View file

@ -1054,6 +1054,7 @@ static const struct user_driver_funcs lazy_load_driver =
.pUnregisterHotKey = loaderdrv_UnregisterHotKey,
.pVkKeyScanEx = loaderdrv_VkKeyScanEx,
.pUpdateClipboard = loaderdrv_UpdateClipboard,
.pScrollDC = nulldrv_ScrollDC,
};
const struct user_driver_funcs *user_driver = &lazy_load_driver;

View file

@ -277,11 +277,6 @@ static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
return pt[1].y - pt[0].y;
}
static inline BOOL is_win9x(void)
{
return NtCurrentTeb()->Peb->OSPlatformId == VER_PLATFORM_WIN32s;
}
static inline WCHAR *strdupW( const WCHAR *p )
{
WCHAR *ret;

View file

@ -1175,6 +1175,7 @@ static struct unix_funcs unix_funcs =
NtUserGetUpdatedClipboardFormats,
NtUserIsClipboardFormatAvailable,
NtUserMapVirtualKeyEx,
NtUserScrollDC,
NtUserToUnicodeEx,
NtUserUnregisterHotKey,
NtUserVkKeyScanEx,

View file

@ -905,3 +905,115 @@ BOOL WINAPI NtGdiDrawStream( HDC hdc, ULONG in, void *pvin )
FIXME("stub: %p, %d, %p\n", hdc, in, pvin);
return FALSE;
}
/*************************************************************************
* NtUserScrollDC (win32u.@)
*/
BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect )
{
HRGN update_rgn = ret_update_rgn;
RECT src_rect, clip_rect, offset;
INT dxdev, dydev;
HRGN dstrgn, cliprgn, visrgn;
POINT org;
DC *dc;
BOOL ret;
TRACE( "dx,dy %d,%d scroll %s clip %s update %p rect %p\n",
dx, dy, wine_dbgstr_rect(scroll), wine_dbgstr_rect(clip), ret_update_rgn, update_rect );
if (!(dc = get_dc_ptr( hdc ))) return FALSE;
org.x = dc->attr->vis_rect.left;
org.y = dc->attr->vis_rect.top;
release_dc_ptr( dc );
/* get the visible region */
visrgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
NtGdiGetRandomRgn( hdc, visrgn, SYSRGN );
if (!is_win9x()) NtGdiOffsetRgn( visrgn, -org.x, -org.y );
/* intersect with the clipping region if the DC has one */
cliprgn = NtGdiCreateRectRgn( 0, 0, 0, 0);
if (NtGdiGetRandomRgn( hdc, cliprgn, NTGDI_RGN_MIRROR_RTL | 1 ) != 1)
{
NtGdiDeleteObjectApp( cliprgn );
cliprgn = 0;
}
else NtGdiCombineRgn( visrgn, visrgn, cliprgn, RGN_AND );
/* only those pixels in the scroll rectangle that remain in the clipping
* rect are scrolled. */
if (clip)
clip_rect = *clip;
else
NtGdiGetAppClipBox( hdc, &clip_rect );
src_rect = clip_rect;
offset_rect( &clip_rect, -dx, -dy );
intersect_rect( &src_rect, &src_rect, &clip_rect );
/* if an scroll rectangle is specified, only the pixels within that
* rectangle are scrolled */
if (scroll) intersect_rect( &src_rect, &src_rect, scroll );
/* now convert to device coordinates */
NtGdiTransformPoints( hdc, (POINT *)&src_rect, (POINT *)&src_rect, 2, NtGdiLPtoDP );
TRACE( "source rect: %s\n", wine_dbgstr_rect(&src_rect) );
/* also dx and dy */
SetRect( &offset, 0, 0, dx, dy );
NtGdiTransformPoints( hdc, (POINT *)&offset, (POINT *)&offset, 2, NtGdiLPtoDP );
dxdev = offset.right - offset.left;
dydev = offset.bottom - offset.top;
/* now intersect with the visible region to get the pixels that will actually scroll */
dstrgn = NtGdiCreateRectRgn( src_rect.left, src_rect.top, src_rect.right, src_rect.bottom );
NtGdiCombineRgn( dstrgn, dstrgn, visrgn, RGN_AND );
NtGdiOffsetRgn( dstrgn, dxdev, dydev );
NtGdiExtSelectClipRgn( hdc, dstrgn, RGN_AND );
/* compute the update areas. This is the combined clip rectangle
* minus the scrolled region, and intersected with the visible region. */
if (ret_update_rgn || update_rect)
{
/* intersect clip and scroll rectangles, allowing NULL values */
if (scroll)
{
if (clip)
intersect_rect( &clip_rect, clip, scroll );
else
clip_rect = *scroll;
}
else if (clip)
clip_rect = *clip;
else
NtGdiGetAppClipBox( hdc, &clip_rect );
/* Convert the combined clip rectangle to device coordinates */
NtGdiTransformPoints( hdc, (POINT *)&clip_rect, (POINT *)&clip_rect, 2, NtGdiLPtoDP );
if (update_rgn)
NtGdiSetRectRgn( update_rgn, clip_rect.left, clip_rect.top,
clip_rect.right, clip_rect.bottom );
else
update_rgn = NtGdiCreateRectRgn( clip_rect.left, clip_rect.top,
clip_rect.right, clip_rect.bottom );
NtGdiCombineRgn( update_rgn, update_rgn, visrgn, RGN_AND );
NtGdiCombineRgn( update_rgn, update_rgn, dstrgn, RGN_DIFF );
}
ret = user_driver->pScrollDC( hdc, dx, dy, update_rgn );
if (ret && update_rect)
{
NtGdiGetRgnBox( update_rgn, update_rect );
NtGdiTransformPoints( hdc, (POINT *)&update_rect, (POINT *)&update_rect, 2, NtGdiDPtoLP );
TRACE( "returning update_rect %s\n", wine_dbgstr_rect(update_rect) );
}
if (!ret_update_rgn) NtGdiDeleteObjectApp( update_rgn );
NtGdiExtSelectClipRgn( hdc, cliprgn, RGN_COPY );
if (cliprgn) NtGdiDeleteObjectApp( cliprgn );
NtGdiDeleteObjectApp( visrgn );
NtGdiDeleteObjectApp( dstrgn );
return ret;
}

View file

@ -1155,7 +1155,7 @@
@ stub NtUserResolveDesktopForWOW
@ stub NtUserRestoreWindowDpiChanges
@ stub NtUserSBGetParms
@ stub NtUserScrollDC
@ stdcall NtUserScrollDC(long long long ptr ptr long ptr)
@ stub NtUserScrollWindowEx
@ stub NtUserSelectPalette
@ stub NtUserSendEventMessage

View file

@ -202,6 +202,8 @@ struct unix_funcs
BOOL (WINAPI *pNtUserGetUpdatedClipboardFormats)( UINT *formats, UINT size, UINT *out_size );
BOOL (WINAPI *pNtUserIsClipboardFormatAvailable)( UINT format );
UINT (WINAPI *pNtUserMapVirtualKeyEx)( UINT code, UINT type, HKL layout );
BOOL (WINAPI *pNtUserScrollDC)( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect );
INT (WINAPI *pNtUserToUnicodeEx)( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
BOOL (WINAPI *pNtUserUnregisterHotKey)( HWND hwnd, INT id );
@ -407,4 +409,9 @@ DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *sr
DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src,
DWORD srclen ) DECLSPEC_HIDDEN;
static inline BOOL is_win9x(void)
{
return NtCurrentTeb()->Peb->OSPlatformId == VER_PLATFORM_WIN32s;
}
#endif /* __WINE_WIN32U_PRIVATE */

View file

@ -636,6 +636,12 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout )
return unix_funcs->pNtUserMapVirtualKeyEx( code, type, layout );
}
BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect )
{
return unix_funcs->pNtUserScrollDC( hdc, dx, dy, scroll, clip, ret_update_rgn, update_rect );
}
INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout )
{

View file

@ -92,6 +92,8 @@ HDESK WINAPI NtUserOpenDesktop( OBJECT_ATTRIBUTES *attr, DWORD flags, ACCESS_M
HDESK WINAPI NtUserOpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access );
BOOL WINAPI NtUserRemoveClipboardFormatListener( HWND hwnd );
HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str );
BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect );
BOOL WINAPI NtUserSetKeyboardState( BYTE *state );
BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle );
BOOL WINAPI NtUserSetProp( HWND hwnd, const WCHAR *str, HANDLE handle );