Have USER deal with the caret when scrolling a window.

This commit is contained in:
Dimitrie O. Paun 2002-09-20 19:35:54 +00:00 committed by Alexandre Julliard
parent ac306433eb
commit 9ffa91ef12
3 changed files with 133 additions and 124 deletions

View File

@ -681,7 +681,6 @@ init UserClientDllInitialize
# Wine dll separation hacks, these will go away, don't use them # Wine dll separation hacks, these will go away, don't use them
# #
@ cdecl CARET_GetHwnd() CARET_GetHwnd @ cdecl CARET_GetHwnd() CARET_GetHwnd
@ cdecl CARET_GetRect(ptr) CARET_GetRect
@ cdecl CLIPBOARD_DeleteRecord(ptr long) CLIPBOARD_DeleteRecord @ cdecl CLIPBOARD_DeleteRecord(ptr long) CLIPBOARD_DeleteRecord
@ cdecl CLIPBOARD_EmptyCache(long) CLIPBOARD_EmptyCache @ cdecl CLIPBOARD_EmptyCache(long) CLIPBOARD_EmptyCache
@ cdecl CLIPBOARD_GetFormatName(long ptr long) CLIPBOARD_GetFormatName @ cdecl CLIPBOARD_GetFormatName(long ptr long) CLIPBOARD_GetFormatName
@ -703,7 +702,6 @@ init UserClientDllInitialize
@ cdecl WIN_FindWndPtr(long) WIN_FindWndPtr @ cdecl WIN_FindWndPtr(long) WIN_FindWndPtr
@ cdecl WIN_GetPtr(long) WIN_GetPtr @ cdecl WIN_GetPtr(long) WIN_GetPtr
@ cdecl WIN_Handle32(long) WIN_Handle32 @ cdecl WIN_Handle32(long) WIN_Handle32
@ cdecl WIN_IsWindowDrawable(long long) WIN_IsWindowDrawable
@ cdecl WIN_LinkWindow(long long long) WIN_LinkWindow @ cdecl WIN_LinkWindow(long long long) WIN_LinkWindow
@ cdecl WIN_ListChildren(long) WIN_ListChildren @ cdecl WIN_ListChildren(long) WIN_ListChildren
@ cdecl WIN_ListParents(long) WIN_ListParents @ cdecl WIN_ListParents(long) WIN_ListParents

View File

@ -36,37 +36,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(scroll); WINE_DEFAULT_DEBUG_CHANNEL(scroll);
/*************************************************************************
* 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.@) * ScrollDC (X11DRV.@)
* *
@ -143,102 +112,83 @@ BOOL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, const RECT *rc,
* *
* Note: contrary to what the doc says, pixels that are scrolled from the * Note: contrary to what the doc says, pixels that are scrolled from the
* outside of clipRect to the inside are NOT painted. * 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, INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
const RECT *rect, const RECT *clipRect, const RECT *rect, const RECT *clipRect,
HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags ) HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags )
{ {
INT retVal = NULLREGION; INT retVal;
BOOL bCaret = FALSE, bOwnRgn = TRUE; BOOL bOwnRgn = TRUE;
RECT rc, cliprc; BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
HRGN hrgnClip = CreateRectRgnIndirect(clipRect);
HRGN hrgnTemp;
HDC hDC;
if (!WIN_IsWindowDrawable( hwnd, TRUE )) return ERROR; TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rect=(%d,%d-%d,%d) %04x\n",
hwnd = WIN_GetFullHandle( hwnd ); 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 );
GetClientRect(hwnd, &rc); if( hrgnUpdate ) bOwnRgn = FALSE;
if (rect) IntersectRect(&rc, &rc, rect); else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
if (clipRect) IntersectRect(&cliprc,&rc,clipRect); hDC = GetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE );
else cliprc = rc; if (hDC)
if (!IsRectEmpty(&cliprc) && (dx || dy))
{ {
HDC hDC; HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE)); X11DRV_StartGraphicsExposures( hDC );
HRGN hrgnClip = CreateRectRgnIndirect(&cliprc); X11DRV_ScrollDC( hDC, dx, dy, rect, clipRect, hrgnUpdate, rcUpdate );
HRGN hrgnTemp; X11DRV_EndGraphicsExposures( hDC, hrgn );
RECT caretrc; ReleaseDC( hwnd, hDC );
if (bUpdate) CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_OR );
TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rc=(%d,%d-%d,%d) %04x\n", else RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
hwnd, dx, dy, hrgnUpdate, rcUpdate, DeleteObject( hrgn );
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);
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 );
}
/* 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 );
if( flags & SW_SCROLLCHILDREN )
{
HWND *list = WIN_ListChildren( hwnd );
if (list)
{
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 );
}
}
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 );
} }
/* 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 )
{
HWND *list = WIN_ListChildren( hwnd );
if (list)
{
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, 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( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
DeleteObject( hrgnClip );
return retVal; return retVal;
} }

View File

@ -26,10 +26,42 @@
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "winuser.h" #include "winuser.h"
#include "user.h" #include "user.h"
#include "win.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(scroll); 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.@) * ScrollWindow (USER32.@)
* *
@ -89,8 +121,37 @@ INT WINAPI ScrollWindowEx( HWND hwnd, INT dx, INT dy,
HRGN hrgnUpdate, LPRECT rcUpdate, HRGN hrgnUpdate, LPRECT rcUpdate,
UINT flags ) UINT flags )
{ {
if (USER_Driver.pScrollWindowEx) RECT rc, cliprc;
return USER_Driver.pScrollWindowEx( hwnd, dx, dy, rect, clipRect, INT result;
hrgnUpdate, rcUpdate, flags );
return ERROR; 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;
} }