Conceptually, there is no need for the USER driver to know anything about the caret when it's scrolling a window. USER will hide the caret if need be, call the driver to scroll the window, and then restore the caret. In the process, we no longer need to export: CARET_GetRect WIN_IsWindowDrawable from USER. ChangeLog: Have USER deal with the caret when scrolling a window. Index: dlls/user/user32.spec =================================================================== RCS file: /var/cvs/wine/dlls/user/user32.spec,v retrieving revision 1.52 diff -u -r1.52 user32.spec --- dlls/user/user32.spec 6 Sep 2002 18:51:32 -0000 1.52 +++ dlls/user/user32.spec 19 Sep 2002 05:39:50 -0000 @@ -681,7 +681,6 @@ # Wine dll separation hacks, these will go away, don't use them # @ cdecl CARET_GetHwnd() CARET_GetHwnd -@ cdecl CARET_GetRect(ptr) CARET_GetRect @ cdecl CLIPBOARD_DeleteRecord(ptr long) CLIPBOARD_DeleteRecord @ cdecl CLIPBOARD_EmptyCache(long) CLIPBOARD_EmptyCache @ cdecl CLIPBOARD_GetFormatName(long ptr long) CLIPBOARD_GetFormatName @@ -703,7 +702,6 @@ @ cdecl WIN_FindWndPtr(long) WIN_FindWndPtr @ cdecl WIN_GetPtr(long) WIN_GetPtr @ cdecl WIN_Handle32(long) WIN_Handle32 -@ cdecl WIN_IsWindowDrawable(long long) WIN_IsWindowDrawable @ cdecl WIN_LinkWindow(long long long) WIN_LinkWindow @ cdecl WIN_ListChildren(long) WIN_ListChildren @ cdecl WIN_ListParents(long) WIN_ListParents Index: dlls/x11drv/scroll.c =================================================================== RCS file: /var/cvs/wine/dlls/x11drv/scroll.c,v retrieving revision 1.8 diff -u -r1.8 scroll.c --- dlls/x11drv/scroll.c 31 May 2002 23:40:57 -0000 1.8 +++ dlls/x11drv/scroll.c 19 Sep 2002 05:25:38 -0000 @@ -37,37 +37,6 @@ /************************************************************************* - * fix_caret - */ -static BOOL fix_caret(HWND hWnd, LPRECT lprc, UINT flags) -{ - HWND hCaret = CARET_GetHwnd(); - - if( hCaret ) - { - RECT rc; - CARET_GetRect( &rc ); - if( hCaret == hWnd || - (flags & SW_SCROLLCHILDREN && IsChild(hWnd, hCaret)) ) - { - POINT pt; - pt.x = rc.left; - pt.y = rc.top; - MapWindowPoints( hCaret, hWnd, (LPPOINT)&rc, 2 ); - if( IntersectRect(lprc, lprc, &rc) ) - { - HideCaret(0); - lprc->left = pt.x; - lprc->top = pt.y; - return TRUE; - } - } - } - return FALSE; -} - - -/************************************************************************* * ScrollDC (X11DRV.@) * * Only the hrgnUpdate is returned in device coordinates. @@ -143,102 +112,83 @@ * * Note: contrary to what the doc says, pixels that are scrolled from the * outside of clipRect to the inside are NOT painted. + * + * Parameter are the same as in ScrollWindowEx, with the additional + * requirement that rect and clipRect are _valid_ pointers, to + * rectangles _within_ the client are. Moreover, there is something + * to scroll. */ INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy, const RECT *rect, const RECT *clipRect, HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags ) { - INT retVal = NULLREGION; - BOOL bCaret = FALSE, bOwnRgn = TRUE; - RECT rc, cliprc; - - if (!WIN_IsWindowDrawable( hwnd, TRUE )) return ERROR; - hwnd = WIN_GetFullHandle( hwnd ); - - GetClientRect(hwnd, &rc); - if (rect) IntersectRect(&rc, &rc, rect); - - if (clipRect) IntersectRect(&cliprc,&rc,clipRect); - else cliprc = rc; - - if (!IsRectEmpty(&cliprc) && (dx || dy)) - { - HDC hDC; - BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE)); - HRGN hrgnClip = CreateRectRgnIndirect(&cliprc); - HRGN hrgnTemp; - RECT caretrc; - - TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rc=(%d,%d-%d,%d) %04x\n", - hwnd, dx, dy, hrgnUpdate, rcUpdate, - rc.left, rc.top, rc.right, rc.bottom, flags ); - if (clipRect) TRACE( "cliprc = (%d,%d,%d,%d)\n", - clipRect->left, clipRect->top, - clipRect->right, clipRect->bottom ); - - caretrc = rc; - bCaret = fix_caret(hwnd, &caretrc, flags); + INT retVal; + BOOL bOwnRgn = TRUE; + BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE)); + HRGN hrgnClip = CreateRectRgnIndirect(clipRect); + HRGN hrgnTemp; + HDC hDC; + + TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rect=(%d,%d-%d,%d) %04x\n", + hwnd, dx, dy, hrgnUpdate, rcUpdate, + rect->left, rect->top, rect->right, rect->bottom, flags ); + TRACE( "clipRect = (%d,%d,%d,%d)\n", + clipRect->left, clipRect->top, clipRect->right, clipRect->bottom ); - if( hrgnUpdate ) bOwnRgn = FALSE; - else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ); + if( hrgnUpdate ) bOwnRgn = FALSE; + else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ); - hDC = GetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE ); - if (hDC) - { - HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); - X11DRV_StartGraphicsExposures( hDC ); - X11DRV_ScrollDC( hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate ); - X11DRV_EndGraphicsExposures( hDC, hrgn ); - ReleaseDC( hwnd, hDC ); - if (bUpdate) CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_OR ); - else RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); - DeleteObject( hrgn ); - } + hDC = GetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE ); + if (hDC) + { + HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); + X11DRV_StartGraphicsExposures( hDC ); + X11DRV_ScrollDC( hDC, dx, dy, rect, clipRect, hrgnUpdate, rcUpdate ); + X11DRV_EndGraphicsExposures( hDC, hrgn ); + ReleaseDC( hwnd, hDC ); + if (bUpdate) CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_OR ); + else RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); + DeleteObject( hrgn ); + } - /* Take into account the fact that some damages may have occured during the scroll */ - hrgnTemp = CreateRectRgn( 0, 0, 0, 0 ); - if (GetUpdateRgn( hwnd, hrgnTemp, FALSE ) != NULLREGION) - { - OffsetRgn( hrgnTemp, dx, dy ); - CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND ); - RedrawWindow( hwnd, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE ); - } - DeleteObject( hrgnTemp ); + /* Take into account the fact that some damages may have occured during the scroll */ + hrgnTemp = CreateRectRgn( 0, 0, 0, 0 ); + retVal = GetUpdateRgn( hwnd, hrgnTemp, FALSE ); + if (retVal != NULLREGION) + { + OffsetRgn( hrgnTemp, dx, dy ); + CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND ); + RedrawWindow( hwnd, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE ); + } + DeleteObject( hrgnTemp ); - if( flags & SW_SCROLLCHILDREN ) + if( flags & SW_SCROLLCHILDREN ) + { + HWND *list = WIN_ListChildren( hwnd ); + if (list) { - HWND *list = WIN_ListChildren( hwnd ); - - if (list) + int i; + RECT r, dummy; + for (i = 0; list[i]; i++) { - int i; - RECT r, dummy; - for (i = 0; list[i]; i++) - { - GetWindowRect( list[i], &r ); - MapWindowPoints( 0, hwnd, (POINT *)&r, 2 ); - if (!rect || IntersectRect(&dummy, &r, &rc)) - SetWindowPos( 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 ); + GetWindowRect( list[i], &r ); + MapWindowPoints( 0, hwnd, (POINT *)&r, 2 ); + if (!rect || IntersectRect(&dummy, &r, rect)) + SetWindowPos( 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) ) - RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | - ((flags & SW_ERASE) ? RDW_ERASENOW : 0) | - ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) ); - - if( bCaret ) - { - SetCaretPos( caretrc.left + dx, caretrc.top + dy ); - ShowCaret(0); - } - - if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate ); - DeleteObject( hrgnClip ); } + + if( flags & (SW_INVALIDATE | SW_ERASE) ) + RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | + ((flags & SW_ERASE) ? RDW_ERASENOW : 0) | + ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) ); + + if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate ); + DeleteObject( hrgnClip ); + return retVal; } Index: windows/scroll.c =================================================================== RCS file: /var/cvs/wine/windows/scroll.c,v retrieving revision 1.36 diff -u -r1.36 scroll.c --- windows/scroll.c 31 May 2002 23:06:54 -0000 1.36 +++ windows/scroll.c 19 Sep 2002 05:58:48 -0000 @@ -26,11 +26,43 @@ #include "wine/winuser16.h" #include "winuser.h" #include "user.h" +#include "win.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(scroll); /************************************************************************* + * fix_caret + */ +static HWND fix_caret(HWND hWnd, LPRECT lprc, UINT flags) +{ + HWND hCaret = CARET_GetHwnd(); + + if( hCaret ) + { + RECT rc; + CARET_GetRect( &rc ); + if( hCaret == hWnd || + (flags & SW_SCROLLCHILDREN && IsChild(hWnd, hCaret)) ) + { + POINT pt; + pt.x = rc.left; + pt.y = rc.top; + MapWindowPoints( hCaret, hWnd, (LPPOINT)&rc, 2 ); + if( IntersectRect(lprc, lprc, &rc) ) + { + HideCaret(hCaret); + lprc->left = pt.x; + lprc->top = pt.y; + return hCaret; + } + } + } + return 0; +} + + +/************************************************************************* * ScrollWindow (USER32.@) * */ @@ -89,8 +121,37 @@ HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags ) { - if (USER_Driver.pScrollWindowEx) - return USER_Driver.pScrollWindowEx( hwnd, dx, dy, rect, clipRect, - hrgnUpdate, rcUpdate, flags ); - return ERROR; + RECT rc, cliprc; + INT result; + + if (!WIN_IsWindowDrawable( hwnd, TRUE )) return ERROR; + hwnd = WIN_GetFullHandle( hwnd ); + + GetClientRect(hwnd, &rc); + if (rect) IntersectRect(&rc, &rc, rect); + + if (clipRect) IntersectRect(&cliprc,&rc,clipRect); + else cliprc = rc; + + if (!IsRectEmpty(&cliprc) && (dx || dy)) + { + RECT caretrc = rc; + HWND hwndCaret = fix_caret(hwnd, &caretrc, flags); + + if (USER_Driver.pScrollWindowEx) + result = USER_Driver.pScrollWindowEx( hwnd, dx, dy, &rc, &cliprc, + hrgnUpdate, rcUpdate, flags ); + else + result = ERROR; /* FIXME: we should have a fallback implementation */ + + if( hwndCaret ) + { + SetCaretPos( caretrc.left + dx, caretrc.top + dy ); + ShowCaret(hwndCaret); + } + } + else + result = NULLREGION; + + return result; }