Commit b2db69ef authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

win32u: Move NtUserScrollWindowEx implementation from user32.

parent ff66d8ee
...@@ -1708,8 +1708,8 @@ static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy) ...@@ -1708,8 +1708,8 @@ static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy)
GetClientRect(es->hwndSelf, &rc1); GetClientRect(es->hwndSelf, &rc1);
IntersectRect(&rc, &rc1, &es->format_rect); IntersectRect(&rc, &rc1, &es->format_rect);
ScrollWindowEx(es->hwndSelf, -dx, dy, NtUserScrollWindowEx(es->hwndSelf, -dx, dy,
NULL, &rc, NULL, NULL, SW_INVALIDATE); NULL, &rc, NULL, NULL, SW_INVALIDATE);
/* force scroll info update */ /* force scroll info update */
EDIT_UpdateScrollInfo(es); EDIT_UpdateScrollInfo(es);
} }
......
...@@ -439,8 +439,8 @@ static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll ) ...@@ -439,8 +439,8 @@ static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll )
else else
dy = (descr->top_item - index) * descr->item_height; dy = (descr->top_item - index) * descr->item_height;
ScrollWindowEx( descr->self, dx, dy, NULL, NULL, 0, NULL, NtUserScrollWindowEx( descr->self, dx, dy, NULL, NULL, 0, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
} }
else else
InvalidateRect( descr->self, NULL, TRUE ); InvalidateRect( descr->self, NULL, TRUE );
...@@ -1340,8 +1340,8 @@ static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos ) ...@@ -1340,8 +1340,8 @@ static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos )
/* Invalidate the focused item so it will be repainted correctly */ /* Invalidate the focused item so it will be repainted correctly */
if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1) if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
InvalidateRect( descr->self, &rect, TRUE ); InvalidateRect( descr->self, &rect, TRUE );
ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL, NtUserScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
} }
else else
InvalidateRect( descr->self, NULL, TRUE ); InvalidateRect( descr->self, NULL, TRUE );
......
...@@ -1822,11 +1822,11 @@ void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam, ...@@ -1822,11 +1822,11 @@ void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE); SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
if( uMsg == WM_VSCROLL ) if( uMsg == WM_VSCROLL )
ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL, NtUserScrollWindowEx( hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
else else
ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL, NtUserScrollWindowEx( hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
done: done:
SetThreadDpiAwarenessContext( context ); SetThreadDpiAwarenessContext( context );
} }
......
...@@ -19,72 +19,7 @@ ...@@ -19,72 +19,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "user_private.h" #include "user_private.h"
#include "win.h"
#include "controls.h"
#include "wine/server.h"
#include "wine/list.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(win);
/*************************************************************************
* fix_caret
*
* Helper for ScrollWindowEx:
* If the return value is 0, no special caret handling is necessary.
* Otherwise the return value is the handle of the window that owns the
* caret. Its caret needs to be hidden during the scroll operation and
* moved to new_caret_pos if move_caret is TRUE.
*/
static HWND fix_caret(HWND hWnd, const RECT *scroll_rect, INT dx, INT dy,
UINT flags, LPBOOL move_caret, LPPOINT new_caret_pos)
{
GUITHREADINFO info;
RECT rect, mapped_rcCaret;
info.cbSize = sizeof(info);
if (!NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info )) return 0;
if (!info.hwndCaret) return 0;
mapped_rcCaret = info.rcCaret;
if (info.hwndCaret == hWnd)
{
/* The caret needs to be moved along with scrolling even if it's
* outside the visible area. Otherwise, when the caret is scrolled
* out from the view, the position won't get updated anymore and
* the caret will never scroll back again. */
*move_caret = TRUE;
new_caret_pos->x = info.rcCaret.left + dx;
new_caret_pos->y = info.rcCaret.top + dy;
}
else
{
*move_caret = FALSE;
if (!(flags & SW_SCROLLCHILDREN) || !IsChild(hWnd, info.hwndCaret))
return 0;
MapWindowPoints(info.hwndCaret, hWnd, (LPPOINT)&mapped_rcCaret, 2);
}
/* If the caret is not in the src/dest rects, all is fine done. */
if (!IntersectRect(&rect, scroll_rect, &mapped_rcCaret))
{
rect = *scroll_rect;
OffsetRect(&rect, dx, dy);
if (!IntersectRect(&rect, &rect, &mapped_rcCaret))
return 0;
}
/* Indicate that the caret needs to be updated during the scrolling. */
return info.hwndCaret;
}
/*********************************************************************** /***********************************************************************
...@@ -197,177 +132,6 @@ BOOL WINAPI ValidateRect( HWND hwnd, const RECT *rect ) ...@@ -197,177 +132,6 @@ BOOL WINAPI ValidateRect( HWND hwnd, const RECT *rect )
} }
static INT scroll_window( HWND hwnd, INT dx, INT dy, const RECT *rect, const RECT *clipRect,
HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags, BOOL is_ex )
{
INT retVal = NULLREGION;
BOOL bOwnRgn = TRUE;
BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
int rdw_flags;
HRGN hrgnTemp;
HRGN hrgnWinupd = 0;
HDC hDC;
RECT rc, cliprc;
HWND hwndCaret = NULL;
BOOL moveCaret = FALSE;
POINT newCaretPos;
TRACE( "%p, %d,%d hrgnUpdate=%p rcUpdate = %p %s %04x\n",
hwnd, dx, dy, hrgnUpdate, rcUpdate, wine_dbgstr_rect(rect), flags );
TRACE( "clipRect = %s\n", wine_dbgstr_rect(clipRect));
if( flags & ~( SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE))
FIXME("some flags (%04x) are unhandled\n", flags);
rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ?
RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
if (!WIN_IsWindowDrawable( hwnd, TRUE )) return ERROR;
hwnd = WIN_GetFullHandle( hwnd );
GetClientRect(hwnd, &rc);
if (clipRect) IntersectRect(&cliprc,&rc,clipRect);
else cliprc = rc;
if (rect) IntersectRect(&rc, &rc, rect);
if( hrgnUpdate ) bOwnRgn = FALSE;
else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
newCaretPos.x = newCaretPos.y = 0;
if( !IsRectEmpty(&cliprc) && (dx || dy)) {
DWORD dcxflags = 0;
DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
hwndCaret = fix_caret(hwnd, &rc, dx, dy, flags, &moveCaret, &newCaretPos);
if (hwndCaret)
NtUserHideCaret( hwndCaret );
if (is_ex) dcxflags |= DCX_CACHE;
if( style & WS_CLIPSIBLINGS) dcxflags |= DCX_CLIPSIBLINGS;
if( GetClassLongW( hwnd, GCL_STYLE ) & CS_PARENTDC)
dcxflags |= DCX_PARENTCLIP;
if( !(flags & SW_SCROLLCHILDREN) && (style & WS_CLIPCHILDREN))
dcxflags |= DCX_CLIPCHILDREN;
hDC = NtUserGetDCEx( hwnd, 0, dcxflags);
if (hDC)
{
NtUserScrollDC( hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate );
NtUserReleaseDC( hwnd, hDC );
if (!bUpdate)
NtUserRedrawWindow( hwnd, NULL, hrgnUpdate, rdw_flags);
}
/* If the windows has an update region, this must be
* scrolled as well. Keep a copy in hrgnWinupd
* to be added to hrngUpdate at the end. */
hrgnTemp = CreateRectRgn( 0, 0, 0, 0 );
retVal = NtUserGetUpdateRgn( hwnd, hrgnTemp, FALSE );
if (retVal != NULLREGION)
{
HRGN hrgnClip = CreateRectRgnIndirect(&cliprc);
if( !bOwnRgn) {
hrgnWinupd = CreateRectRgn( 0, 0, 0, 0);
CombineRgn( hrgnWinupd, hrgnTemp, 0, RGN_COPY);
}
OffsetRgn( hrgnTemp, dx, dy );
CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND );
if( !bOwnRgn)
CombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR );
NtUserRedrawWindow( hwnd, NULL, hrgnTemp, rdw_flags);
/* Catch the case where the scrolling amount exceeds the size of the
* original window. This generated a second update area that is the
* location where the original scrolled content would end up.
* This second region is not returned by the ScrollDC and sets
* ScrollWindowEx apart from just a ScrollDC.
*
* This has been verified with testing on windows.
*/
if (abs(dx) > abs(rc.right - rc.left) ||
abs(dy) > abs(rc.bottom - rc.top))
{
SetRectRgn( hrgnTemp, rc.left + dx, rc.top + dy, rc.right+dx, rc.bottom + dy);
CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND );
CombineRgn( hrgnUpdate, hrgnUpdate, hrgnTemp, RGN_OR );
if (rcUpdate)
{
RECT rcTemp;
GetRgnBox( hrgnTemp, &rcTemp );
UnionRect( rcUpdate, rcUpdate, &rcTemp );
}
if( !bOwnRgn)
CombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR );
}
DeleteObject( hrgnClip );
}
DeleteObject( hrgnTemp );
} else {
/* nothing was scrolled */
if( !bOwnRgn)
SetRectRgn( hrgnUpdate, 0, 0, 0, 0 );
SetRectEmpty( rcUpdate);
}
if( flags & SW_SCROLLCHILDREN )
{
HWND *list = WIN_ListChildren( hwnd );
if (list)
{
int i;
RECT r, dummy;
for (i = 0; list[i]; i++)
{
WIN_GetRectangles( list[i], COORDS_PARENT, &r, NULL );
if (!rect || IntersectRect(&dummy, &r, rect))
NtUserSetWindowPos( list[i], 0, r.left + dx, r.top + dy, 0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
SWP_NOREDRAW | SWP_DEFERERASE );
}
HeapFree( GetProcessHeap(), 0, list );
}
}
if( flags & (SW_INVALIDATE | SW_ERASE) )
NtUserRedrawWindow( hwnd, NULL, hrgnUpdate, rdw_flags |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) );
if( hrgnWinupd) {
CombineRgn( hrgnUpdate, hrgnUpdate, hrgnWinupd, RGN_OR);
DeleteObject( hrgnWinupd);
}
if( moveCaret )
SetCaretPos( newCaretPos.x, newCaretPos.y );
if( hwndCaret )
NtUserShowCaret( hwndCaret );
if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
return retVal;
}
/*************************************************************************
* ScrollWindowEx (USER32.@)
*
* Note: contrary to what the doc says, pixels that are scrolled from the
* outside of clipRect to the inside are NOT painted.
*
*/
INT WINAPI ScrollWindowEx( HWND hwnd, INT dx, INT dy,
const RECT *rect, const RECT *clipRect,
HRGN hrgnUpdate, LPRECT rcUpdate,
UINT flags )
{
return scroll_window( hwnd, dx, dy, rect, clipRect, hrgnUpdate, rcUpdate, flags, TRUE );
}
/************************************************************************* /*************************************************************************
* ScrollWindow (USER32.@) * ScrollWindow (USER32.@)
* *
...@@ -375,8 +139,8 @@ INT WINAPI ScrollWindowEx( HWND hwnd, INT dx, INT dy, ...@@ -375,8 +139,8 @@ INT WINAPI ScrollWindowEx( HWND hwnd, INT dx, INT dy,
BOOL WINAPI ScrollWindow( HWND hwnd, INT dx, INT dy, BOOL WINAPI ScrollWindow( HWND hwnd, INT dx, INT dy,
const RECT *rect, const RECT *clipRect ) const RECT *rect, const RECT *clipRect )
{ {
return scroll_window( hwnd, dx, dy, rect, clipRect, 0, NULL, UINT flags = SW_INVALIDATE | SW_ERASE | (rect ? 0 : SW_SCROLLCHILDREN) | SW_NODCCACHE;
SW_INVALIDATE | SW_ERASE | (rect ? 0 : SW_SCROLLCHILDREN), FALSE ) != ERROR; return NtUserScrollWindowEx( hwnd, dx, dy, rect, clipRect, 0, NULL, flags );
} }
/************************************************************************ /************************************************************************
......
...@@ -630,7 +630,7 @@ ...@@ -630,7 +630,7 @@
@ stdcall ScrollChildren(long long long long) @ stdcall ScrollChildren(long long long long)
@ stdcall ScrollDC(long long long ptr ptr long ptr) NtUserScrollDC @ stdcall ScrollDC(long long long ptr ptr long ptr) NtUserScrollDC
@ stdcall ScrollWindow(long long long ptr ptr) @ stdcall ScrollWindow(long long long ptr ptr)
@ stdcall ScrollWindowEx(long long long ptr ptr long ptr long) @ stdcall ScrollWindowEx(long long long ptr ptr long ptr long) NtUserScrollWindowEx
@ stdcall SendDlgItemMessageA(long long long long long) @ stdcall SendDlgItemMessageA(long long long long long)
@ stdcall SendDlgItemMessageW(long long long long long) @ stdcall SendDlgItemMessageW(long long long long long)
@ stdcall SendIMEMessageExA(long long) @ stdcall SendIMEMessageExA(long long)
......
...@@ -1591,3 +1591,207 @@ BOOL WINAPI NtUserLockWindowUpdate( HWND hwnd ) ...@@ -1591,3 +1591,207 @@ BOOL WINAPI NtUserLockWindowUpdate( HWND hwnd )
} }
return !InterlockedCompareExchangePointer( (void **)&locked_hwnd, hwnd, 0 ); return !InterlockedCompareExchangePointer( (void **)&locked_hwnd, hwnd, 0 );
} }
/*************************************************************************
* fix_caret
*
* Helper for NtUserScrollWindowEx:
* If the return value is 0, no special caret handling is necessary.
* Otherwise the return value is the handle of the window that owns the
* caret. Its caret needs to be hidden during the scroll operation and
* moved to new_caret_pos if move_caret is TRUE.
*/
static HWND fix_caret( HWND hwnd, const RECT *scroll_rect, INT dx, INT dy,
UINT flags, BOOL *move_caret, POINT *new_caret_pos )
{
RECT rect, mapped_caret;
GUITHREADINFO info;
info.cbSize = sizeof(info);
if (!NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info )) return 0;
if (!info.hwndCaret) return 0;
mapped_caret = info.rcCaret;
if (info.hwndCaret == hwnd)
{
/* The caret needs to be moved along with scrolling even if it's
* outside the visible area. Otherwise, when the caret is scrolled
* out from the view, the position won't get updated anymore and
* the caret will never scroll back again. */
*move_caret = TRUE;
new_caret_pos->x = info.rcCaret.left + dx;
new_caret_pos->y = info.rcCaret.top + dy;
}
else
{
*move_caret = FALSE;
if (!(flags & SW_SCROLLCHILDREN) || !is_child( hwnd, info.hwndCaret ))
return 0;
map_window_points( info.hwndCaret, hwnd, (POINT *)&mapped_caret, 2, get_thread_dpi() );
}
/* If the caret is not in the src/dest rects, all is fine done. */
if (!intersect_rect( &rect, scroll_rect, &mapped_caret ))
{
rect = *scroll_rect;
OffsetRect( &rect, dx, dy );
if (!intersect_rect( &rect, &rect, &mapped_caret ))
return 0;
}
/* Indicate that the caret needs to be updated during the scrolling. */
return info.hwndCaret;
}
/*************************************************************************
* NtUserScrollWindowEx (win32u.@)
*
* Note: contrary to what the doc says, pixels that are scrolled from the
* outside of clipRect to the inside are NOT painted.
*/
INT WINAPI NtUserScrollWindowEx( HWND hwnd, INT dx, INT dy, const RECT *rect,
const RECT *clip_rect, HRGN update_rgn,
RECT *update_rect, UINT flags )
{
BOOL update = update_rect || update_rgn || flags & (SW_INVALIDATE | SW_ERASE);
BOOL own_rgn = TRUE, move_caret = FALSE;
HRGN temp_rgn, winupd_rgn = 0;
INT retval = NULLREGION;
HWND caret_hwnd = NULL;
POINT new_caret_pos;
RECT rc, cliprc;
int rdw_flags;
HDC hdc;
TRACE( "%p, %d,%d update_rgn=%p update_rect = %p %s %04x\n",
hwnd, dx, dy, update_rgn, update_rect, wine_dbgstr_rect(rect), flags );
TRACE( "clip_rect = %s\n", wine_dbgstr_rect(clip_rect) );
if (flags & ~(SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE))
FIXME( "some flags (%04x) are unhandled\n", flags );
rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ?
RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE;
if (!is_window_drawable( hwnd, TRUE )) return ERROR;
hwnd = get_full_window_handle( hwnd );
get_client_rect( hwnd, &rc );
if (clip_rect) intersect_rect( &cliprc, &rc, clip_rect );
else cliprc = rc;
if (rect) intersect_rect( &rc, &rc, rect );
if (update_rgn) own_rgn = FALSE;
else if (update) update_rgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
new_caret_pos.x = new_caret_pos.y = 0;
if (!IsRectEmpty( &cliprc ) && (dx || dy))
{
DWORD style = get_window_long( hwnd, GWL_STYLE );
DWORD dcxflags = 0;
caret_hwnd = fix_caret( hwnd, &rc, dx, dy, flags, &move_caret, &new_caret_pos );
if (caret_hwnd) NtUserHideCaret( caret_hwnd );
if (!(flags & SW_NODCCACHE)) dcxflags |= DCX_CACHE;
if (style & WS_CLIPSIBLINGS) dcxflags |= DCX_CLIPSIBLINGS;
if (get_class_long( hwnd, GCL_STYLE, FALSE ) & CS_PARENTDC) dcxflags |= DCX_PARENTCLIP;
if (!(flags & SW_SCROLLCHILDREN) && (style & WS_CLIPCHILDREN))
dcxflags |= DCX_CLIPCHILDREN;
hdc = NtUserGetDCEx( hwnd, 0, dcxflags);
if (hdc)
{
NtUserScrollDC( hdc, dx, dy, &rc, &cliprc, update_rgn, update_rect );
NtUserReleaseDC( hwnd, hdc );
if (!update) NtUserRedrawWindow( hwnd, NULL, update_rgn, rdw_flags );
}
/* If the windows has an update region, this must be scrolled as well.
* Keep a copy in winupd_rgn to be added to hrngUpdate at the end. */
temp_rgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
retval = NtUserGetUpdateRgn( hwnd, temp_rgn, FALSE );
if (retval != NULLREGION)
{
HRGN clip_rgn = NtGdiCreateRectRgn( cliprc.left, cliprc.top,
cliprc.right, cliprc.bottom );
if (!own_rgn)
{
winupd_rgn = NtGdiCreateRectRgn( 0, 0, 0, 0);
NtGdiCombineRgn( winupd_rgn, temp_rgn, 0, RGN_COPY);
}
NtGdiOffsetRgn( temp_rgn, dx, dy );
NtGdiCombineRgn( temp_rgn, temp_rgn, clip_rgn, RGN_AND );
if (!own_rgn) NtGdiCombineRgn( winupd_rgn, winupd_rgn, temp_rgn, RGN_OR );
NtUserRedrawWindow( hwnd, NULL, temp_rgn, rdw_flags );
/*
* Catch the case where the scrolling amount exceeds the size of the
* original window. This generated a second update area that is the
* location where the original scrolled content would end up.
* This second region is not returned by the ScrollDC and sets
* ScrollWindowEx apart from just a ScrollDC.
*
* This has been verified with testing on windows.
*/
if (abs( dx ) > abs( rc.right - rc.left ) || abs( dy ) > abs( rc.bottom - rc.top ))
{
NtGdiSetRectRgn( temp_rgn, rc.left + dx, rc.top + dy, rc.right+dx, rc.bottom + dy );
NtGdiCombineRgn( temp_rgn, temp_rgn, clip_rgn, RGN_AND );
NtGdiCombineRgn( update_rgn, update_rgn, temp_rgn, RGN_OR );
if (update_rect)
{
RECT temp_rect;
NtGdiGetRgnBox( temp_rgn, &temp_rect );
union_rect( update_rect, update_rect, &temp_rect );
}
if (!own_rgn) NtGdiCombineRgn( winupd_rgn, winupd_rgn, temp_rgn, RGN_OR );
}
NtGdiDeleteObjectApp( clip_rgn );
}
NtGdiDeleteObjectApp( temp_rgn );
}
else
{
/* nothing was scrolled */
if (!own_rgn) NtGdiSetRectRgn( update_rgn, 0, 0, 0, 0 );
SetRectEmpty( update_rect );
}
if (flags & SW_SCROLLCHILDREN)
{
HWND *list = list_window_children( 0, hwnd, NULL, 0 );
if (list)
{
RECT r, dummy;
int i;
for (i = 0; list[i]; i++)
{
get_window_rects( list[i], COORDS_PARENT, &r, NULL, get_thread_dpi() );
if (!rect || intersect_rect( &dummy, &r, rect ))
NtUserSetWindowPos( list[i], 0, r.left + dx, r.top + dy, 0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
SWP_NOREDRAW | SWP_DEFERERASE );
}
free( list );
}
}
if (flags & (SW_INVALIDATE | SW_ERASE))
NtUserRedrawWindow( hwnd, NULL, update_rgn, rdw_flags |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) );
if (winupd_rgn)
{
NtGdiCombineRgn( update_rgn, update_rgn, winupd_rgn, RGN_OR );
NtGdiDeleteObjectApp( winupd_rgn );
}
if (move_caret) set_caret_pos( new_caret_pos.x, new_caret_pos.y );
if (caret_hwnd) NtUserShowCaret( caret_hwnd );
if (own_rgn && update_rgn) NtGdiDeleteObjectApp( update_rgn );
return retval;
}
...@@ -1200,6 +1200,7 @@ static struct unix_funcs unix_funcs = ...@@ -1200,6 +1200,7 @@ static struct unix_funcs unix_funcs =
NtUserRegisterHotKey, NtUserRegisterHotKey,
NtUserReleaseDC, NtUserReleaseDC,
NtUserScrollDC, NtUserScrollDC,
NtUserScrollWindowEx,
NtUserSelectPalette, NtUserSelectPalette,
NtUserSendInput, NtUserSendInput,
NtUserSetActiveWindow, NtUserSetActiveWindow,
......
...@@ -1156,7 +1156,7 @@ ...@@ -1156,7 +1156,7 @@
@ stub NtUserRestoreWindowDpiChanges @ stub NtUserRestoreWindowDpiChanges
@ stub NtUserSBGetParms @ stub NtUserSBGetParms
@ stdcall NtUserScrollDC(long long long ptr ptr long ptr) @ stdcall NtUserScrollDC(long long long ptr ptr long ptr)
@ stub NtUserScrollWindowEx @ stdcall NtUserScrollWindowEx(long long long ptr ptr long ptr long)
@ stdcall NtUserSelectPalette(long long long) @ stdcall NtUserSelectPalette(long long long)
@ stub NtUserSendEventMessage @ stub NtUserSendEventMessage
@ stdcall NtUserSendInput(long ptr long) @ stdcall NtUserSendInput(long ptr long)
......
...@@ -268,6 +268,9 @@ struct unix_funcs ...@@ -268,6 +268,9 @@ struct unix_funcs
INT (WINAPI *pNtUserReleaseDC)( HWND hwnd, HDC hdc ); INT (WINAPI *pNtUserReleaseDC)( HWND hwnd, HDC hdc );
BOOL (WINAPI *pNtUserScrollDC)( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip, BOOL (WINAPI *pNtUserScrollDC)( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect ); HRGN ret_update_rgn, RECT *update_rect );
INT (WINAPI *pNtUserScrollWindowEx)( HWND hwnd, INT dx, INT dy, const RECT *rect,
const RECT *clip_rect, HRGN update_rgn,
RECT *update_rect, UINT flags );
HPALETTE (WINAPI *pNtUserSelectPalette)( HDC hdc, HPALETTE hpal, WORD bkg ); HPALETTE (WINAPI *pNtUserSelectPalette)( HDC hdc, HPALETTE hpal, WORD bkg );
UINT (WINAPI *pNtUserSendInput)( UINT count, INPUT *inputs, int size ); UINT (WINAPI *pNtUserSendInput)( UINT count, INPUT *inputs, int size );
HWND (WINAPI *pNtUserSetActiveWindow)( HWND hwnd ); HWND (WINAPI *pNtUserSetActiveWindow)( HWND hwnd );
...@@ -449,6 +452,7 @@ extern HWND is_current_process_window( HWND hwnd ) DECLSPEC_HIDDEN; ...@@ -449,6 +452,7 @@ extern HWND is_current_process_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND is_current_thread_window( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND is_current_thread_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL is_desktop_window( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_desktop_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL is_iconic( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_iconic( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL is_window_drawable( HWND hwnd, BOOL icon ) DECLSPEC_HIDDEN;
extern BOOL is_window_enabled( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_window_enabled( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL is_window_unicode( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_window_unicode( HWND hwnd ) DECLSPEC_HIDDEN;
extern DWORD get_window_long( HWND hwnd, INT offset ) DECLSPEC_HIDDEN; extern DWORD get_window_long( HWND hwnd, INT offset ) DECLSPEC_HIDDEN;
......
...@@ -762,7 +762,7 @@ static BOOL is_window_visible( HWND hwnd ) ...@@ -762,7 +762,7 @@ static BOOL is_window_visible( HWND hwnd )
* minimized, and it is itself not minimized unless we are * minimized, and it is itself not minimized unless we are
* trying to draw its default class icon. * trying to draw its default class icon.
*/ */
static BOOL is_window_drawable( HWND hwnd, BOOL icon ) BOOL is_window_drawable( HWND hwnd, BOOL icon )
{ {
HWND *list; HWND *list;
BOOL retval = TRUE; BOOL retval = TRUE;
......
...@@ -1112,6 +1112,15 @@ BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const R ...@@ -1112,6 +1112,15 @@ BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const R
return unix_funcs->pNtUserScrollDC( hdc, dx, dy, scroll, clip, ret_update_rgn, update_rect ); return unix_funcs->pNtUserScrollDC( hdc, dx, dy, scroll, clip, ret_update_rgn, update_rect );
} }
INT WINAPI NtUserScrollWindowEx( HWND hwnd, INT dx, INT dy, const RECT *rect,
const RECT *clip_rect, HRGN update_rgn,
RECT *update_rect, UINT flags )
{
if (!unix_funcs) return 0;
return unix_funcs->pNtUserScrollWindowEx( hwnd, dx, dy, rect, clip_rect,
update_rgn, update_rect, flags );
}
HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE hpal, WORD bkg ) HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE hpal, WORD bkg )
{ {
if (!unix_funcs) return 0; if (!unix_funcs) return 0;
......
...@@ -227,6 +227,9 @@ struct send_message_callback_params ...@@ -227,6 +227,9 @@ struct send_message_callback_params
#define NTUSER_OBJ_ACCEL 0x08 #define NTUSER_OBJ_ACCEL 0x08
#define NTUSER_OBJ_HOOK 0x0f #define NTUSER_OBJ_HOOK 0x0f
/* NtUserScrollWindowEx flag */
#define SW_NODCCACHE 0x8000
/* NtUserInitializeClientPfnArrays parameter, not compatible with Windows */ /* NtUserInitializeClientPfnArrays parameter, not compatible with Windows */
struct user_client_procs struct user_client_procs
{ {
...@@ -615,6 +618,9 @@ BOOL WINAPI NtUserRemoveMenu( HMENU menu, UINT id, UINT flags ); ...@@ -615,6 +618,9 @@ BOOL WINAPI NtUserRemoveMenu( HMENU menu, UINT id, UINT flags );
HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str ); HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str );
BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip, BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect ); HRGN ret_update_rgn, RECT *update_rect );
INT WINAPI NtUserScrollWindowEx( HWND hwnd, INT dx, INT dy, const RECT *rect,
const RECT *clip_rect, HRGN update_rgn,
RECT *update_rect, UINT flags ) DECLSPEC_HIDDEN;
HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE palette, WORD force_background ); HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE palette, WORD force_background );
UINT WINAPI NtUserSendInput( UINT count, INPUT *inputs, int size ); UINT WINAPI NtUserSendInput( UINT count, INPUT *inputs, int size );
HWND WINAPI NtUserSetActiveWindow( HWND hwnd ); HWND WINAPI NtUserSetActiveWindow( HWND hwnd );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment