Started rewrite of painting functions for multiple processes. Moved
BeginPaint to dlls/user. Fixed bug in paint count handling.
This commit is contained in:
parent
9c6af0a490
commit
4964c0f185
|
@ -23,6 +23,7 @@ C_SRCS = \
|
|||
mouse.c \
|
||||
msg16.c \
|
||||
network.c \
|
||||
painting.c \
|
||||
property.c \
|
||||
resource.c \
|
||||
text.c \
|
||||
|
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Window painting functions
|
||||
*
|
||||
* Copyright 1993, 1994, 1995, 2001 Alexandre Julliard
|
||||
* Copyright 1999 Alex Korobka
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "wingdi.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "wine/server.h"
|
||||
#include "win.h"
|
||||
#include "dce.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(win);
|
||||
|
||||
/***********************************************************************
|
||||
* add_paint_count
|
||||
*
|
||||
* Add an increment (normally 1 or -1) to the current paint count of a window.
|
||||
*/
|
||||
static void add_paint_count( HWND hwnd, int incr )
|
||||
{
|
||||
SERVER_START_REQ( inc_window_paint_count )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
req->incr = incr;
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* copy_rgn
|
||||
*
|
||||
* copy a region, doing the right thing if the source region is 0 or 1
|
||||
*/
|
||||
static HRGN copy_rgn( HRGN hSrc )
|
||||
{
|
||||
if (hSrc > 1)
|
||||
{
|
||||
HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
|
||||
CombineRgn( hrgn, hSrc, 0, RGN_COPY );
|
||||
return hrgn;
|
||||
}
|
||||
return hSrc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_update_regions
|
||||
*
|
||||
* Return update regions for the whole window and for the client area.
|
||||
*/
|
||||
static void get_update_regions( WND *win, HRGN *whole_rgn, HRGN *client_rgn )
|
||||
{
|
||||
if (win->hrgnUpdate > 1)
|
||||
{
|
||||
RECT client, update;
|
||||
|
||||
/* check if update rgn overlaps with nonclient area */
|
||||
GetRgnBox( win->hrgnUpdate, &update );
|
||||
client = win->rectClient;
|
||||
OffsetRect( &client, -win->rectWindow.left, -win->rectWindow.top );
|
||||
|
||||
if (update.left < client.left || update.top < client.top ||
|
||||
update.right > client.right || update.bottom > client.bottom)
|
||||
{
|
||||
*whole_rgn = copy_rgn( win->hrgnUpdate );
|
||||
*client_rgn = CreateRectRgnIndirect( &client );
|
||||
if (CombineRgn( *client_rgn, *client_rgn, win->hrgnUpdate, RGN_AND ) == NULLREGION)
|
||||
{
|
||||
DeleteObject( *client_rgn );
|
||||
*client_rgn = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*whole_rgn = 0;
|
||||
*client_rgn = copy_rgn( win->hrgnUpdate );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*client_rgn = *whole_rgn = win->hrgnUpdate; /* 0 or 1 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* begin_ncpaint
|
||||
*
|
||||
* Send a WM_NCPAINT message from inside BeginPaint().
|
||||
* Returns update region cropped to client rectangle (and in client coords),
|
||||
* and clears window update region and internal paint flag.
|
||||
*/
|
||||
static HRGN begin_ncpaint( HWND hwnd )
|
||||
{
|
||||
HRGN whole_rgn, client_rgn;
|
||||
WND *wnd = WIN_GetPtr( hwnd );
|
||||
|
||||
if (!wnd || wnd == WND_OTHER_PROCESS) return 0;
|
||||
|
||||
TRACE("hwnd %04x [%04x] ncf %i\n",
|
||||
hwnd, wnd->hrgnUpdate, wnd->flags & WIN_NEEDS_NCPAINT);
|
||||
|
||||
get_update_regions( wnd, &whole_rgn, &client_rgn );
|
||||
|
||||
if (whole_rgn) /* NOTE: WM_NCPAINT allows wParam to be 1 */
|
||||
{
|
||||
WIN_ReleasePtr( wnd );
|
||||
SendMessageA( hwnd, WM_NCPAINT, whole_rgn, 0 );
|
||||
if (whole_rgn > 1) DeleteObject( whole_rgn );
|
||||
/* make sure the window still exists before continuing */
|
||||
if (!(wnd = WIN_GetPtr( hwnd )) || wnd == WND_OTHER_PROCESS)
|
||||
{
|
||||
if (client_rgn > 1) DeleteObject( client_rgn );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (wnd->hrgnUpdate || (wnd->flags & WIN_INTERNAL_PAINT)) add_paint_count( hwnd, -1 );
|
||||
if (wnd->hrgnUpdate > 1) DeleteObject( wnd->hrgnUpdate );
|
||||
wnd->hrgnUpdate = 0;
|
||||
wnd->flags &= ~(WIN_INTERNAL_PAINT | WIN_NEEDS_NCPAINT | WIN_NEEDS_BEGINPAINT);
|
||||
if (client_rgn > 1) OffsetRgn( client_rgn, wnd->rectWindow.left - wnd->rectClient.left,
|
||||
wnd->rectWindow.top - wnd->rectClient.top );
|
||||
WIN_ReleasePtr( wnd );
|
||||
return client_rgn;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BeginPaint (USER32.@)
|
||||
*/
|
||||
HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
|
||||
{
|
||||
INT dcx_flags;
|
||||
BOOL bIcon;
|
||||
HRGN hrgnUpdate;
|
||||
RECT clipRect, clientRect;
|
||||
HWND full_handle;
|
||||
WND *wndPtr;
|
||||
|
||||
if (!(full_handle = WIN_IsCurrentThread( hwnd )))
|
||||
{
|
||||
if (IsWindow(hwnd))
|
||||
FIXME( "window %x belongs to other thread\n", hwnd );
|
||||
return 0;
|
||||
}
|
||||
hwnd = full_handle;
|
||||
|
||||
/* send WM_NCPAINT and retrieve update region */
|
||||
hrgnUpdate = begin_ncpaint( hwnd );
|
||||
if (!hrgnUpdate && !IsWindow( hwnd )) return 0;
|
||||
|
||||
HideCaret( hwnd );
|
||||
|
||||
bIcon = (IsIconic(hwnd) && GetClassLongA(hwnd, GCL_HICON));
|
||||
|
||||
dcx_flags = DCX_INTERSECTRGN | DCX_WINDOWPAINT | DCX_USESTYLE;
|
||||
if (bIcon) dcx_flags |= DCX_WINDOW;
|
||||
|
||||
if (GetClassLongA( hwnd, GCL_STYLE ) & CS_PARENTDC)
|
||||
{
|
||||
/* Don't clip the output to the update region for CS_PARENTDC window */
|
||||
if (hrgnUpdate > 1) DeleteObject( hrgnUpdate );
|
||||
hrgnUpdate = 0;
|
||||
dcx_flags &= ~DCX_INTERSECTRGN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!hrgnUpdate) /* empty region, clip everything */
|
||||
{
|
||||
hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
|
||||
}
|
||||
else if (hrgnUpdate == 1) /* whole client area, don't clip */
|
||||
{
|
||||
hrgnUpdate = 0;
|
||||
dcx_flags &= ~DCX_INTERSECTRGN;
|
||||
}
|
||||
}
|
||||
lps->hdc = GetDCEx( hwnd, hrgnUpdate, dcx_flags );
|
||||
/* ReleaseDC() in EndPaint() will delete the region */
|
||||
|
||||
if (!lps->hdc)
|
||||
{
|
||||
WARN("GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
|
||||
DeleteObject( hrgnUpdate );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* It is possible that the clip box is bigger than the window itself,
|
||||
if CS_PARENTDC flag is set. Windows never return a paint rect bigger
|
||||
than the window itself, so we need to intersect the cliprect with
|
||||
the window */
|
||||
GetClientRect( hwnd, &clientRect );
|
||||
|
||||
GetClipBox( lps->hdc, &clipRect );
|
||||
LPtoDP(lps->hdc, (LPPOINT)&clipRect, 2); /* GetClipBox returns LP */
|
||||
|
||||
IntersectRect(&lps->rcPaint, &clientRect, &clipRect);
|
||||
DPtoLP(lps->hdc, (LPPOINT)&lps->rcPaint, 2); /* we must return LP */
|
||||
|
||||
TRACE("hdc = %x box = (%i,%i - %i,%i)\n",
|
||||
lps->hdc, lps->rcPaint.left, lps->rcPaint.top, lps->rcPaint.right, lps->rcPaint.bottom );
|
||||
|
||||
if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
|
||||
lps->fErase = !(wndPtr->flags & WIN_NEEDS_ERASEBKGND);
|
||||
wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
|
||||
WIN_ReleasePtr( wndPtr );
|
||||
|
||||
if (!lps->fErase)
|
||||
lps->fErase = !SendMessageA( hwnd, bIcon ? WM_ICONERASEBKGND : WM_ERASEBKGND,
|
||||
(WPARAM)lps->hdc, 0 );
|
||||
return lps->hdc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EndPaint (USER32.@)
|
||||
*/
|
||||
BOOL WINAPI EndPaint( HWND hwnd, const PAINTSTRUCT *lps )
|
||||
{
|
||||
ReleaseDC( hwnd, lps->hdc );
|
||||
ShowCaret( hwnd );
|
||||
return TRUE;
|
||||
}
|
|
@ -214,6 +214,38 @@ INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BeginPaint (USER.39)
|
||||
*/
|
||||
HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
BeginPaint( WIN_Handle32(hwnd), &ps );
|
||||
lps->hdc = ps.hdc;
|
||||
lps->fErase = ps.fErase;
|
||||
lps->rcPaint.top = ps.rcPaint.top;
|
||||
lps->rcPaint.left = ps.rcPaint.left;
|
||||
lps->rcPaint.right = ps.rcPaint.right;
|
||||
lps->rcPaint.bottom = ps.rcPaint.bottom;
|
||||
lps->fRestore = ps.fRestore;
|
||||
lps->fIncUpdate = ps.fIncUpdate;
|
||||
return lps->hdc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EndPaint (USER.40)
|
||||
*/
|
||||
BOOL16 WINAPI EndPaint16( HWND16 hwnd, const PAINTSTRUCT16* lps )
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
ps.hdc = lps->hdc;
|
||||
return EndPaint( WIN_Handle32(hwnd), &ps );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* ShowWindow (USER.42)
|
||||
*/
|
||||
|
|
|
@ -278,153 +278,6 @@ copyrgn:
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BeginPaint (USER.39)
|
||||
*/
|
||||
HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
BeginPaint( WIN_Handle32(hwnd), &ps );
|
||||
lps->hdc = ps.hdc;
|
||||
lps->fErase = ps.fErase;
|
||||
lps->rcPaint.top = ps.rcPaint.top;
|
||||
lps->rcPaint.left = ps.rcPaint.left;
|
||||
lps->rcPaint.right = ps.rcPaint.right;
|
||||
lps->rcPaint.bottom = ps.rcPaint.bottom;
|
||||
lps->fRestore = ps.fRestore;
|
||||
lps->fIncUpdate = ps.fIncUpdate;
|
||||
return lps->hdc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BeginPaint (USER32.@)
|
||||
*/
|
||||
HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
|
||||
{
|
||||
BOOL bIcon;
|
||||
HRGN hrgnUpdate;
|
||||
RECT clipRect, clientRect;
|
||||
HWND full_handle;
|
||||
WND *wndPtr;
|
||||
|
||||
if (!(full_handle = WIN_IsCurrentThread( hwnd )))
|
||||
{
|
||||
if (IsWindow(hwnd))
|
||||
FIXME( "window %x belongs to other thread\n", hwnd );
|
||||
return 0;
|
||||
}
|
||||
hwnd = full_handle;
|
||||
|
||||
bIcon = (IsIconic(hwnd) && GetClassLongA(hwnd, GCL_HICON));
|
||||
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
|
||||
wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
|
||||
|
||||
/* send WM_NCPAINT and make sure hrgnUpdate is a valid rgn handle */
|
||||
WIN_UpdateNCRgn( wndPtr, 0, UNC_UPDATE | UNC_IN_BEGINPAINT);
|
||||
|
||||
/*
|
||||
* Make sure the window is still a window. All window locks are suspended
|
||||
* when the WM_NCPAINT is sent.
|
||||
*/
|
||||
if (!IsWindow( hwnd ))
|
||||
{
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( ((hrgnUpdate = wndPtr->hrgnUpdate) != 0) || (wndPtr->flags & WIN_INTERNAL_PAINT))
|
||||
add_paint_count( hwnd, -1 );
|
||||
|
||||
wndPtr->hrgnUpdate = 0;
|
||||
wndPtr->flags &= ~WIN_INTERNAL_PAINT;
|
||||
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
|
||||
HideCaret( hwnd );
|
||||
|
||||
TRACE("hrgnUpdate = %04x, \n", hrgnUpdate);
|
||||
|
||||
if (GetClassLongA( hwnd, GCL_STYLE ) & CS_PARENTDC)
|
||||
{
|
||||
/* Don't clip the output to the update region for CS_PARENTDC window */
|
||||
if( hrgnUpdate )
|
||||
DeleteObject(hrgnUpdate);
|
||||
lps->hdc = GetDCEx( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE |
|
||||
(bIcon ? DCX_WINDOW : 0) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( hrgnUpdate ) /* convert to client coordinates */
|
||||
OffsetRgn( hrgnUpdate, wndPtr->rectWindow.left - wndPtr->rectClient.left,
|
||||
wndPtr->rectWindow.top - wndPtr->rectClient.top );
|
||||
lps->hdc = GetDCEx(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
|
||||
DCX_WINDOWPAINT | DCX_USESTYLE | (bIcon ? DCX_WINDOW : 0) );
|
||||
/* ReleaseDC() in EndPaint() will delete the region */
|
||||
}
|
||||
|
||||
TRACE("hdc = %04x\n", lps->hdc);
|
||||
|
||||
if (!lps->hdc)
|
||||
{
|
||||
WARN("GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* It is possible that the clip box is bigger than the window itself,
|
||||
if CS_PARENTDC flag is set. Windows never return a paint rect bigger
|
||||
than the window itself, so we need to intersect the cliprect with
|
||||
the window */
|
||||
|
||||
GetClientRect( hwnd, &clientRect );
|
||||
|
||||
GetClipBox( lps->hdc, &clipRect );
|
||||
LPtoDP(lps->hdc, (LPPOINT)&clipRect, 2); /* GetClipBox returns LP */
|
||||
|
||||
IntersectRect(&lps->rcPaint, &clientRect, &clipRect);
|
||||
DPtoLP(lps->hdc, (LPPOINT)&lps->rcPaint, 2); /* we must return LP */
|
||||
|
||||
TRACE("box = (%i,%i - %i,%i)\n", lps->rcPaint.left, lps->rcPaint.top,
|
||||
lps->rcPaint.right, lps->rcPaint.bottom );
|
||||
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
|
||||
if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
|
||||
{
|
||||
wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
|
||||
lps->fErase = !SendMessageA(hwnd, (bIcon) ? WM_ICONERASEBKGND : WM_ERASEBKGND,
|
||||
(WPARAM16)lps->hdc, 0 );
|
||||
}
|
||||
else lps->fErase = TRUE;
|
||||
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return lps->hdc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EndPaint (USER.40)
|
||||
*/
|
||||
BOOL16 WINAPI EndPaint16( HWND16 hwnd, const PAINTSTRUCT16* lps )
|
||||
{
|
||||
ReleaseDC16( hwnd, lps->hdc );
|
||||
ShowCaret16( hwnd );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EndPaint (USER32.@)
|
||||
*/
|
||||
BOOL WINAPI EndPaint( HWND hwnd, const PAINTSTRUCT *lps )
|
||||
{
|
||||
ReleaseDC( hwnd, lps->hdc );
|
||||
ShowCaret( hwnd );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RDW_ValidateParent [RDW_UpdateRgns() helper]
|
||||
*
|
||||
|
@ -858,8 +711,6 @@ BOOL WINAPI RedrawWindow( HWND hwnd, const RECT *rectUpdate,
|
|||
{
|
||||
if( !IntersectRect( &r2, &r, rectUpdate ) ) goto END;
|
||||
OffsetRect( &r2, pt.x, pt.y );
|
||||
|
||||
rect2i:
|
||||
if( wndPtr->hrgnUpdate == 0 )
|
||||
wndPtr->hrgnUpdate = CreateRectRgnIndirect( &r2 );
|
||||
else
|
||||
|
@ -869,14 +720,16 @@ rect2i:
|
|||
{
|
||||
if( flags & RDW_FRAME )
|
||||
{
|
||||
if( wndPtr->hrgnUpdate )
|
||||
DeleteObject( wndPtr->hrgnUpdate );
|
||||
wndPtr->hrgnUpdate = 1;
|
||||
if (wndPtr->hrgnUpdate) hRgn = 1;
|
||||
else wndPtr->hrgnUpdate = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
GETCLIENTRECTW( wndPtr, r2 );
|
||||
goto rect2i;
|
||||
if( wndPtr->hrgnUpdate == 0 )
|
||||
wndPtr->hrgnUpdate = CreateRectRgnIndirect( &r2 );
|
||||
else
|
||||
hRgn = CreateRectRgnIndirect( &r2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue