mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 12:24:21 +00:00
[Win32SS]
- Start ordering functions into separate files. svn path=/trunk/; revision=68582
This commit is contained in:
parent
bfb9c92b07
commit
6fe69964e1
7 changed files with 1412 additions and 1375 deletions
|
@ -129,11 +129,13 @@ list(APPEND SOURCE
|
||||||
user/ntuser/monitor.c
|
user/ntuser/monitor.c
|
||||||
user/ntuser/mouse.c
|
user/ntuser/mouse.c
|
||||||
user/ntuser/msgqueue.c
|
user/ntuser/msgqueue.c
|
||||||
|
user/ntuser/nonclient.c
|
||||||
user/ntuser/ntstubs.c
|
user/ntuser/ntstubs.c
|
||||||
user/ntuser/ntuser.c
|
user/ntuser/ntuser.c
|
||||||
user/ntuser/painting.c
|
user/ntuser/painting.c
|
||||||
user/ntuser/prop.c
|
user/ntuser/prop.c
|
||||||
user/ntuser/scrollbar.c
|
user/ntuser/scrollbar.c
|
||||||
|
user/ntuser/scrollex.c
|
||||||
user/ntuser/session.c
|
user/ntuser/session.c
|
||||||
user/ntuser/shutdown.c
|
user/ntuser/shutdown.c
|
||||||
user/ntuser/simplecall.c
|
user/ntuser/simplecall.c
|
||||||
|
|
|
@ -11,25 +11,6 @@
|
||||||
|
|
||||||
DBG_DEFAULT_CHANNEL(UserDefwnd);
|
DBG_DEFAULT_CHANNEL(UserDefwnd);
|
||||||
|
|
||||||
#define UserHasDlgFrameStyle(Style, ExStyle) \
|
|
||||||
(((ExStyle) & WS_EX_DLGMODALFRAME) || \
|
|
||||||
(((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
|
|
||||||
|
|
||||||
#define UserHasThickFrameStyle(Style, ExStyle) \
|
|
||||||
(((Style) & WS_THICKFRAME) && \
|
|
||||||
(!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
|
|
||||||
|
|
||||||
#define UserHasThinFrameStyle(Style, ExStyle) \
|
|
||||||
(((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
|
|
||||||
|
|
||||||
#define ON_LEFT_BORDER(hit) \
|
|
||||||
(((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
|
|
||||||
#define ON_RIGHT_BORDER(hit) \
|
|
||||||
(((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
|
|
||||||
#define ON_TOP_BORDER(hit) \
|
|
||||||
(((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
|
|
||||||
#define ON_BOTTOM_BORDER(hit) \
|
|
||||||
(((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
|
|
||||||
|
|
||||||
HBRUSH FASTCALL
|
HBRUSH FASTCALL
|
||||||
DefWndControlColor(HDC hDC, UINT ctlType)
|
DefWndControlColor(HDC hDC, UINT ctlType)
|
||||||
|
@ -119,538 +100,6 @@ DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FASTCALL
|
|
||||||
UserDrawWindowFrame(HDC hdc,
|
|
||||||
RECTL *rect,
|
|
||||||
ULONG width,
|
|
||||||
ULONG height)
|
|
||||||
{
|
|
||||||
HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
|
|
||||||
NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
|
|
||||||
NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
|
|
||||||
NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -(LONG)height, PATINVERT );
|
|
||||||
NtGdiPatBlt( hdc, rect->right - 1, rect->top, -(LONG)width, rect->bottom - rect->top - height, PATINVERT );
|
|
||||||
NtGdiSelectBrush( hdc, hbrush );
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID FASTCALL
|
|
||||||
UserDrawMovingFrame(HDC hdc,
|
|
||||||
RECTL *rect,
|
|
||||||
BOOL thickframe)
|
|
||||||
{
|
|
||||||
if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
|
|
||||||
else UserDrawWindowFrame(hdc, rect, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* NC_GetInsideRect
|
|
||||||
*
|
|
||||||
* Get the 'inside' rectangle of a window, i.e. the whole window rectangle
|
|
||||||
* but without the borders (if any).
|
|
||||||
*/
|
|
||||||
void FASTCALL
|
|
||||||
NC_GetInsideRect(PWND Wnd, RECT *rect)
|
|
||||||
{
|
|
||||||
ULONG Style;
|
|
||||||
ULONG ExStyle;
|
|
||||||
|
|
||||||
Style = Wnd->style;
|
|
||||||
ExStyle = Wnd->ExStyle;
|
|
||||||
|
|
||||||
rect->top = rect->left = 0;
|
|
||||||
rect->right = Wnd->rcWindow.right - Wnd->rcWindow.left;
|
|
||||||
rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
|
|
||||||
|
|
||||||
if (Style & WS_ICONIC) return;
|
|
||||||
|
|
||||||
/* Remove frame from rectangle */
|
|
||||||
if (UserHasThickFrameStyle(Style, ExStyle ))
|
|
||||||
{
|
|
||||||
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (UserHasDlgFrameStyle(Style, ExStyle ))
|
|
||||||
{
|
|
||||||
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
|
|
||||||
/* FIXME: this isn't in NC_AdjustRect? why not? */
|
|
||||||
if (ExStyle & WS_EX_DLGMODALFRAME)
|
|
||||||
RECTL_vInflateRect( rect, -1, 0 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (UserHasThinFrameStyle(Style, ExStyle))
|
|
||||||
{
|
|
||||||
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* We have additional border information if the window
|
|
||||||
* is a child (but not an MDI child) */
|
|
||||||
if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
|
|
||||||
{
|
|
||||||
if (ExStyle & WS_EX_CLIENTEDGE)
|
|
||||||
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
|
|
||||||
if (ExStyle & WS_EX_STATICEDGE)
|
|
||||||
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG FASTCALL
|
|
||||||
DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
|
|
||||||
{
|
|
||||||
LONG hittest = 0;
|
|
||||||
POINT pt;
|
|
||||||
MSG msg;
|
|
||||||
RECT rectWindow;
|
|
||||||
ULONG Style = Wnd->style;
|
|
||||||
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
|
|
||||||
|
|
||||||
rectWindow = Wnd->rcWindow;
|
|
||||||
|
|
||||||
if ((wParam & 0xfff0) == SC_MOVE)
|
|
||||||
{
|
|
||||||
/* Move pointer at the center of the caption */
|
|
||||||
RECT rect = rectWindow;
|
|
||||||
/* Note: to be exactly centered we should take the different types
|
|
||||||
* of border into account, but it shouldn't make more than a few pixels
|
|
||||||
* of difference so let's not bother with that */
|
|
||||||
if (Style & WS_SYSMENU)
|
|
||||||
rect.left += UserGetSystemMetrics(SM_CXSIZE) + 1;
|
|
||||||
if (Style & WS_MINIMIZEBOX)
|
|
||||||
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
|
|
||||||
if (Style & WS_MAXIMIZEBOX)
|
|
||||||
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
|
|
||||||
pt.x = (rect.right + rect.left) / 2;
|
|
||||||
pt.y = rect.top + UserGetSystemMetrics(SM_CYSIZE)/2;
|
|
||||||
hittest = HTCAPTION;
|
|
||||||
*capturePoint = pt;
|
|
||||||
}
|
|
||||||
else /* SC_SIZE */
|
|
||||||
{
|
|
||||||
pt.x = pt.y = 0;
|
|
||||||
while (!hittest)
|
|
||||||
{
|
|
||||||
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) return 0;
|
|
||||||
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
|
|
||||||
|
|
||||||
switch(msg.message)
|
|
||||||
{
|
|
||||||
case WM_MOUSEMOVE:
|
|
||||||
//// Clamp the mouse position to the window rectangle when starting a window resize.
|
|
||||||
pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
|
|
||||||
pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
|
|
||||||
hittest = GetNCHitEx(Wnd, pt);
|
|
||||||
if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
|
||||||
switch (msg.wParam)
|
|
||||||
{
|
|
||||||
case VK_UP:
|
|
||||||
hittest = HTTOP;
|
|
||||||
pt.x = (rectWindow.left+rectWindow.right)/2;
|
|
||||||
pt.y = rectWindow.top + UserGetSystemMetrics(SM_CYFRAME) / 2;
|
|
||||||
break;
|
|
||||||
case VK_DOWN:
|
|
||||||
hittest = HTBOTTOM;
|
|
||||||
pt.x = (rectWindow.left+rectWindow.right)/2;
|
|
||||||
pt.y = rectWindow.bottom - UserGetSystemMetrics(SM_CYFRAME) / 2;
|
|
||||||
break;
|
|
||||||
case VK_LEFT:
|
|
||||||
hittest = HTLEFT;
|
|
||||||
pt.x = rectWindow.left + UserGetSystemMetrics(SM_CXFRAME) / 2;
|
|
||||||
pt.y = (rectWindow.top+rectWindow.bottom)/2;
|
|
||||||
break;
|
|
||||||
case VK_RIGHT:
|
|
||||||
hittest = HTRIGHT;
|
|
||||||
pt.x = rectWindow.right - UserGetSystemMetrics(SM_CXFRAME) / 2;
|
|
||||||
pt.y = (rectWindow.top+rectWindow.bottom)/2;
|
|
||||||
break;
|
|
||||||
case VK_RETURN:
|
|
||||||
case VK_ESCAPE:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
IntTranslateKbdMessage( &msg, 0 );
|
|
||||||
pti->TIF_flags |= TIF_MOVESIZETRACKING;
|
|
||||||
IntDispatchMessage( &msg );
|
|
||||||
pti->TIF_flags |= TIF_MOVESIZETRACKING;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*capturePoint = pt;
|
|
||||||
}
|
|
||||||
UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
|
|
||||||
co_IntSendMessage(UserHMGetHandle(Wnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(Wnd), MAKELONG(hittest, WM_MOUSEMOVE));
|
|
||||||
return hittest;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// System Command Size and Move
|
|
||||||
//
|
|
||||||
// Perform SC_MOVE and SC_SIZE commands.
|
|
||||||
//
|
|
||||||
VOID FASTCALL
|
|
||||||
DefWndDoSizeMove(PWND pwnd, WORD wParam)
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
RECT sizingRect, mouseRect, origRect, unmodRect;
|
|
||||||
HDC hdc;
|
|
||||||
LONG hittest = (LONG)(wParam & 0x0f);
|
|
||||||
PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL;
|
|
||||||
POINT minTrack, maxTrack;
|
|
||||||
POINT capturePoint, pt;
|
|
||||||
ULONG Style, ExStyle;
|
|
||||||
BOOL thickframe;
|
|
||||||
BOOL iconic;
|
|
||||||
BOOL moved = FALSE;
|
|
||||||
BOOL DragFullWindows = FALSE;
|
|
||||||
PWND pWndParent = NULL;
|
|
||||||
WPARAM syscommand = (wParam & 0xfff0);
|
|
||||||
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
|
|
||||||
//PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
|
|
||||||
// The task bar can grow in size and can not reduce due to the change
|
|
||||||
// in the work area.
|
|
||||||
|
|
||||||
Style = pwnd->style;
|
|
||||||
ExStyle = pwnd->ExStyle;
|
|
||||||
iconic = (Style & WS_MINIMIZE) != 0;
|
|
||||||
|
|
||||||
if ((Style & WS_MAXIMIZE) || !IntIsWindowVisible(pwnd)) return;
|
|
||||||
|
|
||||||
thickframe = UserHasThickFrameStyle(Style, ExStyle) && !iconic;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Show window contents while dragging the window, get flag from registry data.
|
|
||||||
//
|
|
||||||
UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
|
|
||||||
|
|
||||||
pt.x = pti->ptLast.x;
|
|
||||||
pt.y = pti->ptLast.y;
|
|
||||||
capturePoint = pt;
|
|
||||||
UserClipCursor( NULL );
|
|
||||||
|
|
||||||
TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
|
|
||||||
pwnd, syscommand, hittest, pt.x, pt.y);
|
|
||||||
|
|
||||||
if (syscommand == SC_MOVE)
|
|
||||||
{
|
|
||||||
if (!hittest) hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
|
|
||||||
if (!hittest) return;
|
|
||||||
}
|
|
||||||
else /* SC_SIZE */
|
|
||||||
{
|
|
||||||
if (!thickframe) return;
|
|
||||||
if (hittest && (syscommand != SC_MOUSEMENU))
|
|
||||||
{
|
|
||||||
hittest += (HTLEFT - WMSZ_LEFT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
co_UserSetCapture(UserHMGetHandle(pwnd));
|
|
||||||
hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
|
|
||||||
if (!hittest)
|
|
||||||
{
|
|
||||||
IntReleaseCapture();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get min/max info */
|
|
||||||
|
|
||||||
co_WinPosGetMinMaxInfo(pwnd, NULL, NULL, &minTrack, &maxTrack);
|
|
||||||
sizingRect = pwnd->rcWindow;
|
|
||||||
origRect = sizingRect;
|
|
||||||
if (Style & WS_CHILD)
|
|
||||||
{
|
|
||||||
pWndParent = IntGetParent(pwnd);
|
|
||||||
IntGetClientRect( pWndParent, &mouseRect );
|
|
||||||
IntMapWindowPoints( pWndParent, 0, (LPPOINT)&mouseRect, 2 );
|
|
||||||
IntMapWindowPoints( 0, pWndParent, (LPPOINT)&sizingRect, 2 );
|
|
||||||
unmodRect = sizingRect;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!(ExStyle & WS_EX_TOPMOST))
|
|
||||||
{
|
|
||||||
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RECTL_vSetRect(&mouseRect, 0, 0, UserGetSystemMetrics(SM_CXSCREEN), UserGetSystemMetrics(SM_CYSCREEN));
|
|
||||||
}
|
|
||||||
unmodRect = sizingRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ON_LEFT_BORDER(hittest))
|
|
||||||
{
|
|
||||||
mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x+capturePoint.x-sizingRect.left );
|
|
||||||
mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x+capturePoint.x-sizingRect.left );
|
|
||||||
}
|
|
||||||
else if (ON_RIGHT_BORDER(hittest))
|
|
||||||
{
|
|
||||||
mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x+capturePoint.x-sizingRect.right );
|
|
||||||
mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x+capturePoint.x-sizingRect.right );
|
|
||||||
}
|
|
||||||
if (ON_TOP_BORDER(hittest))
|
|
||||||
{
|
|
||||||
mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y+capturePoint.y-sizingRect.top );
|
|
||||||
mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y+capturePoint.y-sizingRect.top);
|
|
||||||
}
|
|
||||||
else if (ON_BOTTOM_BORDER(hittest))
|
|
||||||
{
|
|
||||||
mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y+capturePoint.y-sizingRect.bottom );
|
|
||||||
mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y+capturePoint.y-sizingRect.bottom );
|
|
||||||
}
|
|
||||||
|
|
||||||
hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
|
|
||||||
if (iconic)
|
|
||||||
{
|
|
||||||
DragCursor = pwnd->pcls->spicn;
|
|
||||||
if (DragCursor)
|
|
||||||
{
|
|
||||||
UserReferenceObject(DragCursor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
|
|
||||||
if (CursorHandle)
|
|
||||||
{
|
|
||||||
DragCursor = UserGetCurIconObject(CursorHandle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iconic = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* repaint the window before moving it around */
|
|
||||||
co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
|
|
||||||
|
|
||||||
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
|
|
||||||
|
|
||||||
co_IntSendMessage( UserHMGetHandle(pwnd), WM_ENTERSIZEMOVE, 0, 0 );
|
|
||||||
|
|
||||||
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, UserHMGetHandle(pwnd));
|
|
||||||
|
|
||||||
if (IntGetCapture() != UserHMGetHandle(pwnd)) co_UserSetCapture( UserHMGetHandle(pwnd) );
|
|
||||||
|
|
||||||
pwnd->head.pti->TIF_flags |= TIF_MOVESIZETRACKING;
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
int dx = 0, dy = 0;
|
|
||||||
|
|
||||||
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
|
|
||||||
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
|
|
||||||
|
|
||||||
/* Exit on button-up, Return, or Esc */
|
|
||||||
if ((msg.message == WM_LBUTTONUP) ||
|
|
||||||
((msg.message == WM_KEYDOWN) &&
|
|
||||||
((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
|
|
||||||
|
|
||||||
if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
|
|
||||||
{
|
|
||||||
IntTranslateKbdMessage( &msg , 0 );
|
|
||||||
IntDispatchMessage( &msg );
|
|
||||||
continue; /* We are not interested in other messages */
|
|
||||||
}
|
|
||||||
|
|
||||||
pt = msg.pt;
|
|
||||||
|
|
||||||
if (msg.message == WM_KEYDOWN) switch(msg.wParam)
|
|
||||||
{
|
|
||||||
case VK_UP: pt.y -= 8; break;
|
|
||||||
case VK_DOWN: pt.y += 8; break;
|
|
||||||
case VK_LEFT: pt.x -= 8; break;
|
|
||||||
case VK_RIGHT: pt.x += 8; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pt.x = max( pt.x, mouseRect.left );
|
|
||||||
pt.x = min( pt.x, mouseRect.right - 1 );
|
|
||||||
pt.y = max( pt.y, mouseRect.top );
|
|
||||||
pt.y = min( pt.y, mouseRect.bottom - 1 );
|
|
||||||
|
|
||||||
dx = pt.x - capturePoint.x;
|
|
||||||
dy = pt.y - capturePoint.y;
|
|
||||||
|
|
||||||
if (dx || dy)
|
|
||||||
{
|
|
||||||
if ( !moved )
|
|
||||||
{
|
|
||||||
moved = TRUE;
|
|
||||||
if ( iconic ) /* ok, no system popup tracking */
|
|
||||||
{
|
|
||||||
OldCursor = UserSetCursor(DragCursor, FALSE);
|
|
||||||
UserShowCursor( TRUE );
|
|
||||||
}
|
|
||||||
else if(!DragFullWindows)
|
|
||||||
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RECT newRect = unmodRect;
|
|
||||||
|
|
||||||
if (!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
|
|
||||||
if (hittest == HTCAPTION) RECTL_vOffsetRect( &newRect, dx, dy );
|
|
||||||
if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
|
|
||||||
else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
|
|
||||||
if (ON_TOP_BORDER(hittest)) newRect.top += dy;
|
|
||||||
else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
|
|
||||||
capturePoint = pt;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Save the new position to the unmodified rectangle. This allows explorer task bar
|
|
||||||
// sizing. Explorer will forces back the position unless a certain amount of sizing
|
|
||||||
// has occurred.
|
|
||||||
//
|
|
||||||
unmodRect = newRect;
|
|
||||||
|
|
||||||
/* determine the hit location */
|
|
||||||
if (syscommand == SC_SIZE)
|
|
||||||
{
|
|
||||||
WPARAM wpSizingHit = 0;
|
|
||||||
|
|
||||||
if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
|
|
||||||
wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
|
|
||||||
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SIZING, wpSizingHit, (LPARAM)&newRect );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
co_IntSendMessage( UserHMGetHandle(pwnd), WM_MOVING, 0, (LPARAM)&newRect );
|
|
||||||
|
|
||||||
if (!iconic)
|
|
||||||
{
|
|
||||||
if (!DragFullWindows)
|
|
||||||
UserDrawMovingFrame( hdc, &newRect, thickframe );
|
|
||||||
else
|
|
||||||
{ // Moving the whole window now!
|
|
||||||
PWND pwndTemp;
|
|
||||||
//// This causes the mdi child window to jump up when it is moved.
|
|
||||||
//IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
|
|
||||||
co_WinPosSetWindowPos( pwnd,
|
|
||||||
0,
|
|
||||||
newRect.left,
|
|
||||||
newRect.top,
|
|
||||||
newRect.right - newRect.left,
|
|
||||||
newRect.bottom - newRect.top,
|
|
||||||
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
|
|
||||||
|
|
||||||
// Update all the windows after the move or size, including this window.
|
|
||||||
for ( pwndTemp = pwnd->head.rpdesk->pDeskInfo->spwnd->spwndChild;
|
|
||||||
pwndTemp;
|
|
||||||
pwndTemp = pwndTemp->spwndNext )
|
|
||||||
{
|
|
||||||
RECTL rect;
|
|
||||||
// Only the windows that overlap will be redrawn.
|
|
||||||
if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
|
|
||||||
{
|
|
||||||
co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sizingRect = newRect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pwnd->head.pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
|
|
||||||
|
|
||||||
IntReleaseCapture();
|
|
||||||
|
|
||||||
if ( iconic )
|
|
||||||
{
|
|
||||||
if ( moved ) /* restore cursors, show icon title later on */
|
|
||||||
{
|
|
||||||
UserShowCursor( FALSE );
|
|
||||||
OldCursor = UserSetCursor(OldCursor, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* It could be that the cursor was already changed while we were proceeding,
|
|
||||||
* so we must unreference whatever cursor was current at the time we restored the old one.
|
|
||||||
* Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
|
|
||||||
*/
|
|
||||||
if (OldCursor) UserDereferenceObject(OldCursor);
|
|
||||||
}
|
|
||||||
else if ( moved && !DragFullWindows )
|
|
||||||
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
|
|
||||||
|
|
||||||
UserReleaseDC(NULL, hdc, FALSE);
|
|
||||||
|
|
||||||
//// This causes the mdi child window to jump up when it is moved.
|
|
||||||
//if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
|
|
||||||
|
|
||||||
if (co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)UserHMGetHandle(pwnd), (LPARAM)&sizingRect))
|
|
||||||
{
|
|
||||||
ERR("DoSizeMove : WH_CBT Call Hook return!\n");
|
|
||||||
moved = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
|
|
||||||
|
|
||||||
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
|
|
||||||
|
|
||||||
co_IntSendMessage( UserHMGetHandle(pwnd), WM_EXITSIZEMOVE, 0, 0 );
|
|
||||||
//// wine mdi hack
|
|
||||||
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SETVISIBLE, !!(pwnd->style & WS_MINIMIZE), 0L);
|
|
||||||
////
|
|
||||||
/* window moved or resized */
|
|
||||||
if (moved)
|
|
||||||
{
|
|
||||||
/* if the moving/resizing isn't canceled call SetWindowPos
|
|
||||||
* with the new position or the new size of the window
|
|
||||||
*/
|
|
||||||
if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
|
|
||||||
{
|
|
||||||
/* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
|
|
||||||
if (!DragFullWindows || iconic )
|
|
||||||
{
|
|
||||||
co_WinPosSetWindowPos( pwnd,
|
|
||||||
0,
|
|
||||||
sizingRect.left,
|
|
||||||
sizingRect.top,
|
|
||||||
sizingRect.right - sizingRect.left,
|
|
||||||
sizingRect.bottom - sizingRect.top,
|
|
||||||
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* restore previous size/position */
|
|
||||||
if ( DragFullWindows )
|
|
||||||
{
|
|
||||||
co_WinPosSetWindowPos( pwnd,
|
|
||||||
0,
|
|
||||||
origRect.left,
|
|
||||||
origRect.top,
|
|
||||||
origRect.right - origRect.left,
|
|
||||||
origRect.bottom - origRect.top,
|
|
||||||
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( IntIsWindow(UserHMGetHandle(pwnd)) )
|
|
||||||
{
|
|
||||||
if ( iconic )
|
|
||||||
{
|
|
||||||
/* Single click brings up the system menu when iconized */
|
|
||||||
if ( !moved )
|
|
||||||
{
|
|
||||||
if( Style & WS_SYSMENU )
|
|
||||||
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
|
// Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
|
||||||
//
|
//
|
||||||
|
@ -1197,230 +646,4 @@ IntDefWindowProc(
|
||||||
return lResult;
|
return lResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
|
|
||||||
{
|
|
||||||
PCURICON_OBJECT pIcon = NULL;
|
|
||||||
HICON hIcon;
|
|
||||||
|
|
||||||
//FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
|
|
||||||
//FIXME: Hence we must return a pointer with no reference count.
|
|
||||||
//FIXME: This is bad and we should feel bad.
|
|
||||||
//FIXME: Stop whining over wine code.
|
|
||||||
|
|
||||||
hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
|
|
||||||
if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
|
|
||||||
|
|
||||||
if (!hIcon && pWnd->pcls->spicnSm)
|
|
||||||
return pWnd->pcls->spicnSm;
|
|
||||||
if (!hIcon && pWnd->pcls->spicn)
|
|
||||||
return pWnd->pcls->spicn;
|
|
||||||
|
|
||||||
if (!hIcon && (pWnd->style & DS_MODALFRAME))
|
|
||||||
{
|
|
||||||
if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
|
|
||||||
if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size.
|
|
||||||
}
|
|
||||||
if (hIcon)
|
|
||||||
{
|
|
||||||
pIcon = UserGetCurIconObject(hIcon);
|
|
||||||
if (pIcon)
|
|
||||||
{
|
|
||||||
UserDereferenceObject(pIcon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD FASTCALL
|
|
||||||
GetNCHitEx(PWND pWnd, POINT pt)
|
|
||||||
{
|
|
||||||
RECT rcWindow, rcClient;
|
|
||||||
DWORD Style, ExStyle;
|
|
||||||
|
|
||||||
if (!pWnd) return HTNOWHERE;
|
|
||||||
|
|
||||||
if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
|
|
||||||
{
|
|
||||||
rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
|
|
||||||
rcWindow.right = UserGetSystemMetrics(SM_CXSCREEN);
|
|
||||||
rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
|
|
||||||
rcClient.right = UserGetSystemMetrics(SM_CXSCREEN);
|
|
||||||
rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rcClient = pWnd->rcClient;
|
|
||||||
rcWindow = pWnd->rcWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
|
|
||||||
|
|
||||||
Style = pWnd->style;
|
|
||||||
ExStyle = pWnd->ExStyle;
|
|
||||||
|
|
||||||
if (Style & WS_MINIMIZE) return HTCAPTION;
|
|
||||||
|
|
||||||
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTCLIENT;
|
|
||||||
|
|
||||||
/* Check borders */
|
|
||||||
if (HAS_THICKFRAME( Style, ExStyle ))
|
|
||||||
{
|
|
||||||
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
|
|
||||||
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
|
|
||||||
{
|
|
||||||
/* Check top sizing border */
|
|
||||||
if (pt.y < rcWindow.top)
|
|
||||||
{
|
|
||||||
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
|
|
||||||
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
|
|
||||||
return HTTOP;
|
|
||||||
}
|
|
||||||
/* Check bottom sizing border */
|
|
||||||
if (pt.y >= rcWindow.bottom)
|
|
||||||
{
|
|
||||||
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
|
|
||||||
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
|
|
||||||
return HTBOTTOM;
|
|
||||||
}
|
|
||||||
/* Check left sizing border */
|
|
||||||
if (pt.x < rcWindow.left)
|
|
||||||
{
|
|
||||||
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
|
|
||||||
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
|
|
||||||
return HTLEFT;
|
|
||||||
}
|
|
||||||
/* Check right sizing border */
|
|
||||||
if (pt.x >= rcWindow.right)
|
|
||||||
{
|
|
||||||
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
|
|
||||||
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
|
|
||||||
return HTRIGHT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* No thick frame */
|
|
||||||
{
|
|
||||||
if (HAS_DLGFRAME( Style, ExStyle ))
|
|
||||||
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
|
|
||||||
else if (HAS_THINFRAME( Style, ExStyle ))
|
|
||||||
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
|
|
||||||
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) return HTBORDER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check caption */
|
|
||||||
|
|
||||||
if ((Style & WS_CAPTION) == WS_CAPTION)
|
|
||||||
{
|
|
||||||
if (ExStyle & WS_EX_TOOLWINDOW)
|
|
||||||
rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
|
|
||||||
else
|
|
||||||
rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
|
|
||||||
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
|
|
||||||
{
|
|
||||||
BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX));
|
|
||||||
if (ExStyle & WS_EX_LAYOUTRTL)
|
|
||||||
{
|
|
||||||
/* Check system menu */
|
|
||||||
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
|
|
||||||
{
|
|
||||||
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
|
|
||||||
if (pt.x > rcWindow.right) return HTSYSMENU;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check close button */
|
|
||||||
if (Style & WS_SYSMENU)
|
|
||||||
{
|
|
||||||
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
|
|
||||||
if (pt.x < rcWindow.left) return HTCLOSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check maximize box */
|
|
||||||
/* In Win95 there is automatically a Maximize button when there is a minimize one */
|
|
||||||
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
|
||||||
{
|
|
||||||
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
|
|
||||||
if (pt.x < rcWindow.left) return HTMAXBUTTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check minimize box */
|
|
||||||
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
|
||||||
{
|
|
||||||
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
|
|
||||||
if (pt.x < rcWindow.left) return HTMINBUTTON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Check system menu */
|
|
||||||
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
|
|
||||||
{
|
|
||||||
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
|
|
||||||
if (pt.x < rcWindow.left) return HTSYSMENU;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check close button */
|
|
||||||
if (Style & WS_SYSMENU)
|
|
||||||
{
|
|
||||||
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
|
|
||||||
if (pt.x > rcWindow.right) return HTCLOSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check maximize box */
|
|
||||||
/* In Win95 there is automatically a Maximize button when there is a minimize one */
|
|
||||||
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
|
||||||
{
|
|
||||||
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
|
|
||||||
if (pt.x > rcWindow.right) return HTMAXBUTTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check minimize box */
|
|
||||||
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
|
||||||
{
|
|
||||||
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
|
|
||||||
if (pt.x > rcWindow.right) return HTMINBUTTON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return HTCAPTION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check menu bar */
|
|
||||||
|
|
||||||
if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
|
|
||||||
(pt.x >= rcClient.left) && (pt.x < rcClient.right))
|
|
||||||
return HTMENU;
|
|
||||||
|
|
||||||
/* Check vertical scroll bar */
|
|
||||||
|
|
||||||
if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
|
|
||||||
if (Style & WS_VSCROLL)
|
|
||||||
{
|
|
||||||
if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
|
|
||||||
rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
|
|
||||||
else
|
|
||||||
rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
|
|
||||||
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check horizontal scroll bar */
|
|
||||||
|
|
||||||
if (Style & WS_HSCROLL)
|
|
||||||
{
|
|
||||||
rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
|
|
||||||
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
|
|
||||||
{
|
|
||||||
/* Check size box */
|
|
||||||
if ((Style & WS_VSCROLL) &&
|
|
||||||
((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
|
|
||||||
(((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
|
|
||||||
return HTSIZE;
|
|
||||||
return HTHSCROLL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Has to return HTNOWHERE if nothing was found
|
|
||||||
Could happen when a window has a customized non client area */
|
|
||||||
return HTNOWHERE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
793
reactos/win32ss/user/ntuser/nonclient.c
Normal file
793
reactos/win32ss/user/ntuser/nonclient.c
Normal file
|
@ -0,0 +1,793 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Win32k subsystem
|
||||||
|
* PURPOSE: Miscellaneous User functions
|
||||||
|
* FILE: win32ss/user/ntuser/nonclient.c
|
||||||
|
* PROGRAMER:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <win32k.h>
|
||||||
|
#include <windowsx.h>
|
||||||
|
|
||||||
|
DBG_DEFAULT_CHANNEL(UserDefwnd);
|
||||||
|
|
||||||
|
#define UserHasDlgFrameStyle(Style, ExStyle) \
|
||||||
|
(((ExStyle) & WS_EX_DLGMODALFRAME) || \
|
||||||
|
(((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
|
||||||
|
|
||||||
|
#define UserHasThickFrameStyle(Style, ExStyle) \
|
||||||
|
(((Style) & WS_THICKFRAME) && \
|
||||||
|
(!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
|
||||||
|
|
||||||
|
#define UserHasThinFrameStyle(Style, ExStyle) \
|
||||||
|
(((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
|
||||||
|
|
||||||
|
#define ON_LEFT_BORDER(hit) \
|
||||||
|
(((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
|
||||||
|
#define ON_RIGHT_BORDER(hit) \
|
||||||
|
(((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
|
||||||
|
#define ON_TOP_BORDER(hit) \
|
||||||
|
(((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
|
||||||
|
#define ON_BOTTOM_BORDER(hit) \
|
||||||
|
(((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
|
||||||
|
|
||||||
|
|
||||||
|
VOID FASTCALL
|
||||||
|
UserDrawWindowFrame(HDC hdc,
|
||||||
|
RECTL *rect,
|
||||||
|
ULONG width,
|
||||||
|
ULONG height)
|
||||||
|
{
|
||||||
|
HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
|
||||||
|
NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
|
||||||
|
NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
|
||||||
|
NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -(LONG)height, PATINVERT );
|
||||||
|
NtGdiPatBlt( hdc, rect->right - 1, rect->top, -(LONG)width, rect->bottom - rect->top - height, PATINVERT );
|
||||||
|
NtGdiSelectBrush( hdc, hbrush );
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FASTCALL
|
||||||
|
UserDrawMovingFrame(HDC hdc,
|
||||||
|
RECTL *rect,
|
||||||
|
BOOL thickframe)
|
||||||
|
{
|
||||||
|
if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
|
||||||
|
else UserDrawWindowFrame(hdc, rect, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* NC_GetInsideRect
|
||||||
|
*
|
||||||
|
* Get the 'inside' rectangle of a window, i.e. the whole window rectangle
|
||||||
|
* but without the borders (if any).
|
||||||
|
*/
|
||||||
|
void FASTCALL
|
||||||
|
NC_GetInsideRect(PWND Wnd, RECT *rect)
|
||||||
|
{
|
||||||
|
ULONG Style;
|
||||||
|
ULONG ExStyle;
|
||||||
|
|
||||||
|
Style = Wnd->style;
|
||||||
|
ExStyle = Wnd->ExStyle;
|
||||||
|
|
||||||
|
rect->top = rect->left = 0;
|
||||||
|
rect->right = Wnd->rcWindow.right - Wnd->rcWindow.left;
|
||||||
|
rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
|
||||||
|
|
||||||
|
if (Style & WS_ICONIC) return;
|
||||||
|
|
||||||
|
/* Remove frame from rectangle */
|
||||||
|
if (UserHasThickFrameStyle(Style, ExStyle ))
|
||||||
|
{
|
||||||
|
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (UserHasDlgFrameStyle(Style, ExStyle ))
|
||||||
|
{
|
||||||
|
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
|
||||||
|
/* FIXME: this isn't in NC_AdjustRect? why not? */
|
||||||
|
if (ExStyle & WS_EX_DLGMODALFRAME)
|
||||||
|
RECTL_vInflateRect( rect, -1, 0 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (UserHasThinFrameStyle(Style, ExStyle))
|
||||||
|
{
|
||||||
|
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* We have additional border information if the window
|
||||||
|
* is a child (but not an MDI child) */
|
||||||
|
if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
|
||||||
|
{
|
||||||
|
if (ExStyle & WS_EX_CLIENTEDGE)
|
||||||
|
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
|
||||||
|
if (ExStyle & WS_EX_STATICEDGE)
|
||||||
|
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG FASTCALL
|
||||||
|
DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
|
||||||
|
{
|
||||||
|
LONG hittest = 0;
|
||||||
|
POINT pt;
|
||||||
|
MSG msg;
|
||||||
|
RECT rectWindow;
|
||||||
|
ULONG Style = Wnd->style;
|
||||||
|
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
|
||||||
|
|
||||||
|
rectWindow = Wnd->rcWindow;
|
||||||
|
|
||||||
|
if ((wParam & 0xfff0) == SC_MOVE)
|
||||||
|
{
|
||||||
|
/* Move pointer at the center of the caption */
|
||||||
|
RECT rect = rectWindow;
|
||||||
|
/* Note: to be exactly centered we should take the different types
|
||||||
|
* of border into account, but it shouldn't make more than a few pixels
|
||||||
|
* of difference so let's not bother with that */
|
||||||
|
if (Style & WS_SYSMENU)
|
||||||
|
rect.left += UserGetSystemMetrics(SM_CXSIZE) + 1;
|
||||||
|
if (Style & WS_MINIMIZEBOX)
|
||||||
|
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
|
||||||
|
if (Style & WS_MAXIMIZEBOX)
|
||||||
|
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
|
||||||
|
pt.x = (rect.right + rect.left) / 2;
|
||||||
|
pt.y = rect.top + UserGetSystemMetrics(SM_CYSIZE)/2;
|
||||||
|
hittest = HTCAPTION;
|
||||||
|
*capturePoint = pt;
|
||||||
|
}
|
||||||
|
else /* SC_SIZE */
|
||||||
|
{
|
||||||
|
pt.x = pt.y = 0;
|
||||||
|
while (!hittest)
|
||||||
|
{
|
||||||
|
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) return 0;
|
||||||
|
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
|
||||||
|
|
||||||
|
switch(msg.message)
|
||||||
|
{
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
//// Clamp the mouse position to the window rectangle when starting a window resize.
|
||||||
|
pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
|
||||||
|
pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
|
||||||
|
hittest = GetNCHitEx(Wnd, pt);
|
||||||
|
if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
switch (msg.wParam)
|
||||||
|
{
|
||||||
|
case VK_UP:
|
||||||
|
hittest = HTTOP;
|
||||||
|
pt.x = (rectWindow.left+rectWindow.right)/2;
|
||||||
|
pt.y = rectWindow.top + UserGetSystemMetrics(SM_CYFRAME) / 2;
|
||||||
|
break;
|
||||||
|
case VK_DOWN:
|
||||||
|
hittest = HTBOTTOM;
|
||||||
|
pt.x = (rectWindow.left+rectWindow.right)/2;
|
||||||
|
pt.y = rectWindow.bottom - UserGetSystemMetrics(SM_CYFRAME) / 2;
|
||||||
|
break;
|
||||||
|
case VK_LEFT:
|
||||||
|
hittest = HTLEFT;
|
||||||
|
pt.x = rectWindow.left + UserGetSystemMetrics(SM_CXFRAME) / 2;
|
||||||
|
pt.y = (rectWindow.top+rectWindow.bottom)/2;
|
||||||
|
break;
|
||||||
|
case VK_RIGHT:
|
||||||
|
hittest = HTRIGHT;
|
||||||
|
pt.x = rectWindow.right - UserGetSystemMetrics(SM_CXFRAME) / 2;
|
||||||
|
pt.y = (rectWindow.top+rectWindow.bottom)/2;
|
||||||
|
break;
|
||||||
|
case VK_RETURN:
|
||||||
|
case VK_ESCAPE:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
IntTranslateKbdMessage( &msg, 0 );
|
||||||
|
pti->TIF_flags |= TIF_MOVESIZETRACKING;
|
||||||
|
IntDispatchMessage( &msg );
|
||||||
|
pti->TIF_flags |= TIF_MOVESIZETRACKING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*capturePoint = pt;
|
||||||
|
}
|
||||||
|
UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
|
||||||
|
co_IntSendMessage(UserHMGetHandle(Wnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(Wnd), MAKELONG(hittest, WM_MOUSEMOVE));
|
||||||
|
return hittest;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// System Command Size and Move
|
||||||
|
//
|
||||||
|
// Perform SC_MOVE and SC_SIZE commands.
|
||||||
|
//
|
||||||
|
VOID FASTCALL
|
||||||
|
DefWndDoSizeMove(PWND pwnd, WORD wParam)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
RECT sizingRect, mouseRect, origRect, unmodRect;
|
||||||
|
HDC hdc;
|
||||||
|
LONG hittest = (LONG)(wParam & 0x0f);
|
||||||
|
PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL;
|
||||||
|
POINT minTrack, maxTrack;
|
||||||
|
POINT capturePoint, pt;
|
||||||
|
ULONG Style, ExStyle;
|
||||||
|
BOOL thickframe;
|
||||||
|
BOOL iconic;
|
||||||
|
BOOL moved = FALSE;
|
||||||
|
BOOL DragFullWindows = FALSE;
|
||||||
|
PWND pWndParent = NULL;
|
||||||
|
WPARAM syscommand = (wParam & 0xfff0);
|
||||||
|
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
|
||||||
|
//PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
|
||||||
|
// The task bar can grow in size and can not reduce due to the change
|
||||||
|
// in the work area.
|
||||||
|
|
||||||
|
Style = pwnd->style;
|
||||||
|
ExStyle = pwnd->ExStyle;
|
||||||
|
iconic = (Style & WS_MINIMIZE) != 0;
|
||||||
|
|
||||||
|
if ((Style & WS_MAXIMIZE) || !IntIsWindowVisible(pwnd)) return;
|
||||||
|
|
||||||
|
thickframe = UserHasThickFrameStyle(Style, ExStyle) && !iconic;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Show window contents while dragging the window, get flag from registry data.
|
||||||
|
//
|
||||||
|
UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
|
||||||
|
|
||||||
|
pt.x = pti->ptLast.x;
|
||||||
|
pt.y = pti->ptLast.y;
|
||||||
|
capturePoint = pt;
|
||||||
|
UserClipCursor( NULL );
|
||||||
|
|
||||||
|
TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
|
||||||
|
pwnd, syscommand, hittest, pt.x, pt.y);
|
||||||
|
|
||||||
|
if (syscommand == SC_MOVE)
|
||||||
|
{
|
||||||
|
if (!hittest) hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
|
||||||
|
if (!hittest) return;
|
||||||
|
}
|
||||||
|
else /* SC_SIZE */
|
||||||
|
{
|
||||||
|
if (!thickframe) return;
|
||||||
|
if (hittest && (syscommand != SC_MOUSEMENU))
|
||||||
|
{
|
||||||
|
hittest += (HTLEFT - WMSZ_LEFT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
co_UserSetCapture(UserHMGetHandle(pwnd));
|
||||||
|
hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
|
||||||
|
if (!hittest)
|
||||||
|
{
|
||||||
|
IntReleaseCapture();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get min/max info */
|
||||||
|
|
||||||
|
co_WinPosGetMinMaxInfo(pwnd, NULL, NULL, &minTrack, &maxTrack);
|
||||||
|
sizingRect = pwnd->rcWindow;
|
||||||
|
origRect = sizingRect;
|
||||||
|
if (Style & WS_CHILD)
|
||||||
|
{
|
||||||
|
pWndParent = IntGetParent(pwnd);
|
||||||
|
IntGetClientRect( pWndParent, &mouseRect );
|
||||||
|
IntMapWindowPoints( pWndParent, 0, (LPPOINT)&mouseRect, 2 );
|
||||||
|
IntMapWindowPoints( 0, pWndParent, (LPPOINT)&sizingRect, 2 );
|
||||||
|
unmodRect = sizingRect;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(ExStyle & WS_EX_TOPMOST))
|
||||||
|
{
|
||||||
|
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RECTL_vSetRect(&mouseRect, 0, 0, UserGetSystemMetrics(SM_CXSCREEN), UserGetSystemMetrics(SM_CYSCREEN));
|
||||||
|
}
|
||||||
|
unmodRect = sizingRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ON_LEFT_BORDER(hittest))
|
||||||
|
{
|
||||||
|
mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x+capturePoint.x-sizingRect.left );
|
||||||
|
mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x+capturePoint.x-sizingRect.left );
|
||||||
|
}
|
||||||
|
else if (ON_RIGHT_BORDER(hittest))
|
||||||
|
{
|
||||||
|
mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x+capturePoint.x-sizingRect.right );
|
||||||
|
mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x+capturePoint.x-sizingRect.right );
|
||||||
|
}
|
||||||
|
if (ON_TOP_BORDER(hittest))
|
||||||
|
{
|
||||||
|
mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y+capturePoint.y-sizingRect.top );
|
||||||
|
mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y+capturePoint.y-sizingRect.top);
|
||||||
|
}
|
||||||
|
else if (ON_BOTTOM_BORDER(hittest))
|
||||||
|
{
|
||||||
|
mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y+capturePoint.y-sizingRect.bottom );
|
||||||
|
mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y+capturePoint.y-sizingRect.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
|
hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
|
||||||
|
if (iconic)
|
||||||
|
{
|
||||||
|
DragCursor = pwnd->pcls->spicn;
|
||||||
|
if (DragCursor)
|
||||||
|
{
|
||||||
|
UserReferenceObject(DragCursor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
|
||||||
|
if (CursorHandle)
|
||||||
|
{
|
||||||
|
DragCursor = UserGetCurIconObject(CursorHandle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iconic = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* repaint the window before moving it around */
|
||||||
|
co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
|
||||||
|
|
||||||
|
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
|
||||||
|
|
||||||
|
co_IntSendMessage( UserHMGetHandle(pwnd), WM_ENTERSIZEMOVE, 0, 0 );
|
||||||
|
|
||||||
|
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, UserHMGetHandle(pwnd));
|
||||||
|
|
||||||
|
if (IntGetCapture() != UserHMGetHandle(pwnd)) co_UserSetCapture( UserHMGetHandle(pwnd) );
|
||||||
|
|
||||||
|
pwnd->head.pti->TIF_flags |= TIF_MOVESIZETRACKING;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
int dx = 0, dy = 0;
|
||||||
|
|
||||||
|
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
|
||||||
|
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
|
||||||
|
|
||||||
|
/* Exit on button-up, Return, or Esc */
|
||||||
|
if ((msg.message == WM_LBUTTONUP) ||
|
||||||
|
((msg.message == WM_KEYDOWN) &&
|
||||||
|
((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
|
||||||
|
|
||||||
|
if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
|
||||||
|
{
|
||||||
|
IntTranslateKbdMessage( &msg , 0 );
|
||||||
|
IntDispatchMessage( &msg );
|
||||||
|
continue; /* We are not interested in other messages */
|
||||||
|
}
|
||||||
|
|
||||||
|
pt = msg.pt;
|
||||||
|
|
||||||
|
if (msg.message == WM_KEYDOWN) switch(msg.wParam)
|
||||||
|
{
|
||||||
|
case VK_UP: pt.y -= 8; break;
|
||||||
|
case VK_DOWN: pt.y += 8; break;
|
||||||
|
case VK_LEFT: pt.x -= 8; break;
|
||||||
|
case VK_RIGHT: pt.x += 8; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pt.x = max( pt.x, mouseRect.left );
|
||||||
|
pt.x = min( pt.x, mouseRect.right - 1 );
|
||||||
|
pt.y = max( pt.y, mouseRect.top );
|
||||||
|
pt.y = min( pt.y, mouseRect.bottom - 1 );
|
||||||
|
|
||||||
|
dx = pt.x - capturePoint.x;
|
||||||
|
dy = pt.y - capturePoint.y;
|
||||||
|
|
||||||
|
if (dx || dy)
|
||||||
|
{
|
||||||
|
if ( !moved )
|
||||||
|
{
|
||||||
|
moved = TRUE;
|
||||||
|
if ( iconic ) /* ok, no system popup tracking */
|
||||||
|
{
|
||||||
|
OldCursor = UserSetCursor(DragCursor, FALSE);
|
||||||
|
UserShowCursor( TRUE );
|
||||||
|
}
|
||||||
|
else if(!DragFullWindows)
|
||||||
|
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RECT newRect = unmodRect;
|
||||||
|
|
||||||
|
if (!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
|
||||||
|
if (hittest == HTCAPTION) RECTL_vOffsetRect( &newRect, dx, dy );
|
||||||
|
if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
|
||||||
|
else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
|
||||||
|
if (ON_TOP_BORDER(hittest)) newRect.top += dy;
|
||||||
|
else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
|
||||||
|
capturePoint = pt;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save the new position to the unmodified rectangle. This allows explorer task bar
|
||||||
|
// sizing. Explorer will forces back the position unless a certain amount of sizing
|
||||||
|
// has occurred.
|
||||||
|
//
|
||||||
|
unmodRect = newRect;
|
||||||
|
|
||||||
|
/* determine the hit location */
|
||||||
|
if (syscommand == SC_SIZE)
|
||||||
|
{
|
||||||
|
WPARAM wpSizingHit = 0;
|
||||||
|
|
||||||
|
if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
|
||||||
|
wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
|
||||||
|
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SIZING, wpSizingHit, (LPARAM)&newRect );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
co_IntSendMessage( UserHMGetHandle(pwnd), WM_MOVING, 0, (LPARAM)&newRect );
|
||||||
|
|
||||||
|
if (!iconic)
|
||||||
|
{
|
||||||
|
if (!DragFullWindows)
|
||||||
|
UserDrawMovingFrame( hdc, &newRect, thickframe );
|
||||||
|
else
|
||||||
|
{ // Moving the whole window now!
|
||||||
|
PWND pwndTemp;
|
||||||
|
//// This causes the mdi child window to jump up when it is moved.
|
||||||
|
//IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
|
||||||
|
co_WinPosSetWindowPos( pwnd,
|
||||||
|
0,
|
||||||
|
newRect.left,
|
||||||
|
newRect.top,
|
||||||
|
newRect.right - newRect.left,
|
||||||
|
newRect.bottom - newRect.top,
|
||||||
|
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
|
||||||
|
|
||||||
|
// Update all the windows after the move or size, including this window.
|
||||||
|
for ( pwndTemp = pwnd->head.rpdesk->pDeskInfo->spwnd->spwndChild;
|
||||||
|
pwndTemp;
|
||||||
|
pwndTemp = pwndTemp->spwndNext )
|
||||||
|
{
|
||||||
|
RECTL rect;
|
||||||
|
// Only the windows that overlap will be redrawn.
|
||||||
|
if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
|
||||||
|
{
|
||||||
|
co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sizingRect = newRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pwnd->head.pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
|
||||||
|
|
||||||
|
IntReleaseCapture();
|
||||||
|
|
||||||
|
if ( iconic )
|
||||||
|
{
|
||||||
|
if ( moved ) /* restore cursors, show icon title later on */
|
||||||
|
{
|
||||||
|
UserShowCursor( FALSE );
|
||||||
|
OldCursor = UserSetCursor(OldCursor, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It could be that the cursor was already changed while we were proceeding,
|
||||||
|
* so we must unreference whatever cursor was current at the time we restored the old one.
|
||||||
|
* Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
|
||||||
|
*/
|
||||||
|
if (OldCursor) UserDereferenceObject(OldCursor);
|
||||||
|
}
|
||||||
|
else if ( moved && !DragFullWindows )
|
||||||
|
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
|
||||||
|
|
||||||
|
UserReleaseDC(NULL, hdc, FALSE);
|
||||||
|
|
||||||
|
//// This causes the mdi child window to jump up when it is moved.
|
||||||
|
//if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
|
||||||
|
|
||||||
|
if (co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)UserHMGetHandle(pwnd), (LPARAM)&sizingRect))
|
||||||
|
{
|
||||||
|
ERR("DoSizeMove : WH_CBT Call Hook return!\n");
|
||||||
|
moved = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
|
||||||
|
|
||||||
|
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
|
||||||
|
|
||||||
|
co_IntSendMessage( UserHMGetHandle(pwnd), WM_EXITSIZEMOVE, 0, 0 );
|
||||||
|
//// wine mdi hack
|
||||||
|
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SETVISIBLE, !!(pwnd->style & WS_MINIMIZE), 0L);
|
||||||
|
////
|
||||||
|
/* window moved or resized */
|
||||||
|
if (moved)
|
||||||
|
{
|
||||||
|
/* if the moving/resizing isn't canceled call SetWindowPos
|
||||||
|
* with the new position or the new size of the window
|
||||||
|
*/
|
||||||
|
if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
|
||||||
|
{
|
||||||
|
/* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
|
||||||
|
if (!DragFullWindows || iconic )
|
||||||
|
{
|
||||||
|
co_WinPosSetWindowPos( pwnd,
|
||||||
|
0,
|
||||||
|
sizingRect.left,
|
||||||
|
sizingRect.top,
|
||||||
|
sizingRect.right - sizingRect.left,
|
||||||
|
sizingRect.bottom - sizingRect.top,
|
||||||
|
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* restore previous size/position */
|
||||||
|
if ( DragFullWindows )
|
||||||
|
{
|
||||||
|
co_WinPosSetWindowPos( pwnd,
|
||||||
|
0,
|
||||||
|
origRect.left,
|
||||||
|
origRect.top,
|
||||||
|
origRect.right - origRect.left,
|
||||||
|
origRect.bottom - origRect.top,
|
||||||
|
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( IntIsWindow(UserHMGetHandle(pwnd)) )
|
||||||
|
{
|
||||||
|
if ( iconic )
|
||||||
|
{
|
||||||
|
/* Single click brings up the system menu when iconized */
|
||||||
|
if ( !moved )
|
||||||
|
{
|
||||||
|
if( Style & WS_SYSMENU )
|
||||||
|
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
|
||||||
|
{
|
||||||
|
PCURICON_OBJECT pIcon = NULL;
|
||||||
|
HICON hIcon;
|
||||||
|
|
||||||
|
//FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
|
||||||
|
//FIXME: Hence we must return a pointer with no reference count.
|
||||||
|
//FIXME: This is bad and we should feel bad.
|
||||||
|
//FIXME: Stop whining over wine code.
|
||||||
|
|
||||||
|
hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
|
||||||
|
if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
|
||||||
|
|
||||||
|
if (!hIcon && pWnd->pcls->spicnSm)
|
||||||
|
return pWnd->pcls->spicnSm;
|
||||||
|
if (!hIcon && pWnd->pcls->spicn)
|
||||||
|
return pWnd->pcls->spicn;
|
||||||
|
|
||||||
|
if (!hIcon && (pWnd->style & DS_MODALFRAME))
|
||||||
|
{
|
||||||
|
if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
|
||||||
|
if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size.
|
||||||
|
}
|
||||||
|
if (hIcon)
|
||||||
|
{
|
||||||
|
pIcon = UserGetCurIconObject(hIcon);
|
||||||
|
if (pIcon)
|
||||||
|
{
|
||||||
|
UserDereferenceObject(pIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD FASTCALL
|
||||||
|
GetNCHitEx(PWND pWnd, POINT pt)
|
||||||
|
{
|
||||||
|
RECT rcWindow, rcClient;
|
||||||
|
DWORD Style, ExStyle;
|
||||||
|
|
||||||
|
if (!pWnd) return HTNOWHERE;
|
||||||
|
|
||||||
|
if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
|
||||||
|
{
|
||||||
|
rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
|
||||||
|
rcWindow.right = UserGetSystemMetrics(SM_CXSCREEN);
|
||||||
|
rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
|
||||||
|
rcClient.right = UserGetSystemMetrics(SM_CXSCREEN);
|
||||||
|
rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rcClient = pWnd->rcClient;
|
||||||
|
rcWindow = pWnd->rcWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
|
||||||
|
|
||||||
|
Style = pWnd->style;
|
||||||
|
ExStyle = pWnd->ExStyle;
|
||||||
|
|
||||||
|
if (Style & WS_MINIMIZE) return HTCAPTION;
|
||||||
|
|
||||||
|
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTCLIENT;
|
||||||
|
|
||||||
|
/* Check borders */
|
||||||
|
if (HAS_THICKFRAME( Style, ExStyle ))
|
||||||
|
{
|
||||||
|
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
|
||||||
|
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
|
||||||
|
{
|
||||||
|
/* Check top sizing border */
|
||||||
|
if (pt.y < rcWindow.top)
|
||||||
|
{
|
||||||
|
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
|
||||||
|
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
|
||||||
|
return HTTOP;
|
||||||
|
}
|
||||||
|
/* Check bottom sizing border */
|
||||||
|
if (pt.y >= rcWindow.bottom)
|
||||||
|
{
|
||||||
|
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
|
||||||
|
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
|
||||||
|
return HTBOTTOM;
|
||||||
|
}
|
||||||
|
/* Check left sizing border */
|
||||||
|
if (pt.x < rcWindow.left)
|
||||||
|
{
|
||||||
|
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
|
||||||
|
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
|
||||||
|
return HTLEFT;
|
||||||
|
}
|
||||||
|
/* Check right sizing border */
|
||||||
|
if (pt.x >= rcWindow.right)
|
||||||
|
{
|
||||||
|
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
|
||||||
|
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
|
||||||
|
return HTRIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* No thick frame */
|
||||||
|
{
|
||||||
|
if (HAS_DLGFRAME( Style, ExStyle ))
|
||||||
|
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
|
||||||
|
else if (HAS_THINFRAME( Style, ExStyle ))
|
||||||
|
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
|
||||||
|
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) return HTBORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check caption */
|
||||||
|
|
||||||
|
if ((Style & WS_CAPTION) == WS_CAPTION)
|
||||||
|
{
|
||||||
|
if (ExStyle & WS_EX_TOOLWINDOW)
|
||||||
|
rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
|
||||||
|
else
|
||||||
|
rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
|
||||||
|
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
|
||||||
|
{
|
||||||
|
BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX));
|
||||||
|
if (ExStyle & WS_EX_LAYOUTRTL)
|
||||||
|
{
|
||||||
|
/* Check system menu */
|
||||||
|
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
|
||||||
|
{
|
||||||
|
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
|
||||||
|
if (pt.x > rcWindow.right) return HTSYSMENU;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check close button */
|
||||||
|
if (Style & WS_SYSMENU)
|
||||||
|
{
|
||||||
|
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
|
||||||
|
if (pt.x < rcWindow.left) return HTCLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check maximize box */
|
||||||
|
/* In Win95 there is automatically a Maximize button when there is a minimize one */
|
||||||
|
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
||||||
|
{
|
||||||
|
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
|
||||||
|
if (pt.x < rcWindow.left) return HTMAXBUTTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check minimize box */
|
||||||
|
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
||||||
|
{
|
||||||
|
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
|
||||||
|
if (pt.x < rcWindow.left) return HTMINBUTTON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check system menu */
|
||||||
|
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
|
||||||
|
{
|
||||||
|
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
|
||||||
|
if (pt.x < rcWindow.left) return HTSYSMENU;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check close button */
|
||||||
|
if (Style & WS_SYSMENU)
|
||||||
|
{
|
||||||
|
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
|
||||||
|
if (pt.x > rcWindow.right) return HTCLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check maximize box */
|
||||||
|
/* In Win95 there is automatically a Maximize button when there is a minimize one */
|
||||||
|
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
||||||
|
{
|
||||||
|
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
|
||||||
|
if (pt.x > rcWindow.right) return HTMAXBUTTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check minimize box */
|
||||||
|
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
|
||||||
|
{
|
||||||
|
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
|
||||||
|
if (pt.x > rcWindow.right) return HTMINBUTTON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HTCAPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check menu bar */
|
||||||
|
|
||||||
|
if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
|
||||||
|
(pt.x >= rcClient.left) && (pt.x < rcClient.right))
|
||||||
|
return HTMENU;
|
||||||
|
|
||||||
|
/* Check vertical scroll bar */
|
||||||
|
|
||||||
|
if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
|
||||||
|
if (Style & WS_VSCROLL)
|
||||||
|
{
|
||||||
|
if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
|
||||||
|
rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
|
||||||
|
else
|
||||||
|
rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
|
||||||
|
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check horizontal scroll bar */
|
||||||
|
|
||||||
|
if (Style & WS_HSCROLL)
|
||||||
|
{
|
||||||
|
rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
|
||||||
|
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
|
||||||
|
{
|
||||||
|
/* Check size box */
|
||||||
|
if ((Style & WS_VSCROLL) &&
|
||||||
|
((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
|
||||||
|
(((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
|
||||||
|
return HTSIZE;
|
||||||
|
return HTHSCROLL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Has to return HTNOWHERE if nothing was found
|
||||||
|
Could happen when a window has a customized non client area */
|
||||||
|
return HTNOWHERE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
|
@ -1127,55 +1127,6 @@ IntGetPaintMessage(
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
HWND FASTCALL
|
|
||||||
co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
|
|
||||||
{
|
|
||||||
PDESKTOP Desktop;
|
|
||||||
PTHRDCARETINFO CaretInfo;
|
|
||||||
PTHREADINFO pti;
|
|
||||||
PUSER_MESSAGE_QUEUE ActiveMessageQueue;
|
|
||||||
HWND hWndCaret;
|
|
||||||
PWND WndCaret;
|
|
||||||
|
|
||||||
ASSERT_REFS_CO(Window);
|
|
||||||
|
|
||||||
pti = PsGetCurrentThreadWin32Thread();
|
|
||||||
Desktop = pti->rpdesk;
|
|
||||||
ActiveMessageQueue = Desktop->ActiveMessageQueue;
|
|
||||||
if (!ActiveMessageQueue) return 0;
|
|
||||||
CaretInfo = ActiveMessageQueue->CaretInfo;
|
|
||||||
hWndCaret = CaretInfo->hWnd;
|
|
||||||
|
|
||||||
WndCaret = ValidateHwndNoErr(hWndCaret);
|
|
||||||
|
|
||||||
// FIXME: Check for WndCaret can be NULL
|
|
||||||
if (WndCaret == Window ||
|
|
||||||
((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
|
|
||||||
{
|
|
||||||
POINT pt, FromOffset, ToOffset;
|
|
||||||
RECTL rcCaret;
|
|
||||||
|
|
||||||
pt.x = CaretInfo->Pos.x;
|
|
||||||
pt.y = CaretInfo->Pos.y;
|
|
||||||
IntGetClientOrigin(WndCaret, &FromOffset);
|
|
||||||
IntGetClientOrigin(Window, &ToOffset);
|
|
||||||
rcCaret.left = pt.x;
|
|
||||||
rcCaret.top = pt.y;
|
|
||||||
rcCaret.right = pt.x + CaretInfo->Size.cx;
|
|
||||||
rcCaret.bottom = pt.y + CaretInfo->Size.cy;
|
|
||||||
if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
|
|
||||||
{
|
|
||||||
co_UserHideCaret(0);
|
|
||||||
lprc->left = pt.x;
|
|
||||||
lprc->top = pt.y;
|
|
||||||
return hWndCaret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
FASTCALL
|
FASTCALL
|
||||||
IntPrintWindow(
|
IntPrintWindow(
|
||||||
|
@ -1914,553 +1865,6 @@ CLEANUP:
|
||||||
END_CLEANUP;
|
END_CLEANUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Old GetUpdateRgn, for scrolls, see above note.
|
|
||||||
*/
|
|
||||||
INT FASTCALL
|
|
||||||
co_IntGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
|
|
||||||
{
|
|
||||||
int RegionType;
|
|
||||||
RECTL Rect;
|
|
||||||
PREGION UpdateRgn;
|
|
||||||
|
|
||||||
ASSERT_REFS_CO(Window);
|
|
||||||
|
|
||||||
if (bErase)
|
|
||||||
{
|
|
||||||
co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Window->state &= ~WNDS_UPDATEDIRTY;
|
|
||||||
|
|
||||||
if (Window->hrgnUpdate == NULL)
|
|
||||||
{
|
|
||||||
REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
|
|
||||||
return NULLREGION;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateRgn = REGION_LockRgn(Window->hrgnUpdate);
|
|
||||||
if (!UpdateRgn)
|
|
||||||
return ERROR;
|
|
||||||
|
|
||||||
Rect = Window->rcClient;
|
|
||||||
IntIntersectWithParents(Window, &Rect);
|
|
||||||
REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
|
|
||||||
RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
|
|
||||||
REGION_bOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
|
|
||||||
REGION_UnlockRgn(UpdateRgn);
|
|
||||||
|
|
||||||
return RegionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
INT FASTCALL
|
|
||||||
UserScrollDC(
|
|
||||||
HDC hDC,
|
|
||||||
INT dx,
|
|
||||||
INT dy,
|
|
||||||
const RECTL *prcScroll,
|
|
||||||
const RECTL *prcClip,
|
|
||||||
HRGN hrgnUpdate,
|
|
||||||
PREGION RgnUpdate,
|
|
||||||
RECTL *prcUpdate)
|
|
||||||
{
|
|
||||||
PDC pDC;
|
|
||||||
RECTL rcScroll, rcClip, rcSrc, rcDst;
|
|
||||||
INT Result;
|
|
||||||
|
|
||||||
if (GdiGetClipBox(hDC, &rcClip) == ERROR)
|
|
||||||
{
|
|
||||||
ERR("GdiGetClipBox failed for HDC %p\n", hDC);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcScroll = rcClip;
|
|
||||||
if (prcClip)
|
|
||||||
{
|
|
||||||
RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prcScroll)
|
|
||||||
{
|
|
||||||
rcScroll = *prcScroll;
|
|
||||||
RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rcSrc = rcClip;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcDst = rcSrc;
|
|
||||||
RECTL_vOffsetRect(&rcDst, dx, dy);
|
|
||||||
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
|
|
||||||
|
|
||||||
if (!NtGdiBitBlt( hDC,
|
|
||||||
rcDst.left,
|
|
||||||
rcDst.top,
|
|
||||||
rcDst.right - rcDst.left,
|
|
||||||
rcDst.bottom - rcDst.top,
|
|
||||||
hDC,
|
|
||||||
rcDst.left - dx,
|
|
||||||
rcDst.top - dy,
|
|
||||||
SRCCOPY,
|
|
||||||
0,
|
|
||||||
0))
|
|
||||||
{
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the region that was invalidated by moving or
|
|
||||||
could not be copied, because it was not visible */
|
|
||||||
if (RgnUpdate || hrgnUpdate || prcUpdate)
|
|
||||||
{
|
|
||||||
PREGION RgnOwn, RgnTmp;
|
|
||||||
|
|
||||||
pDC = DC_LockDc(hDC);
|
|
||||||
if (!pDC)
|
|
||||||
{
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hrgnUpdate)
|
|
||||||
{
|
|
||||||
NT_ASSERT(RgnUpdate == NULL);
|
|
||||||
RgnUpdate = REGION_LockRgn(hrgnUpdate);
|
|
||||||
if (!RgnUpdate)
|
|
||||||
{
|
|
||||||
DC_UnlockDc(pDC);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Begin with the shifted and then clipped scroll rect */
|
|
||||||
rcDst = rcScroll;
|
|
||||||
RECTL_vOffsetRect(&rcDst, dx, dy);
|
|
||||||
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
|
|
||||||
if (RgnUpdate)
|
|
||||||
{
|
|
||||||
RgnOwn = RgnUpdate;
|
|
||||||
REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the source rect */
|
|
||||||
RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
|
|
||||||
IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
|
|
||||||
|
|
||||||
/* Substract the part of the dest that was visible in source */
|
|
||||||
IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
|
|
||||||
REGION_bOffsetRgn(RgnTmp, dx, dy);
|
|
||||||
Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
|
|
||||||
|
|
||||||
/* DO NOT Unlock DC while messing with prgnVis! */
|
|
||||||
DC_UnlockDc(pDC);
|
|
||||||
|
|
||||||
REGION_Delete(RgnTmp);
|
|
||||||
|
|
||||||
if (prcUpdate)
|
|
||||||
{
|
|
||||||
REGION_GetRgnBox(RgnOwn, prcUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hrgnUpdate)
|
|
||||||
{
|
|
||||||
REGION_UnlockRgn(RgnUpdate);
|
|
||||||
}
|
|
||||||
else if (!RgnUpdate)
|
|
||||||
{
|
|
||||||
REGION_Delete(RgnOwn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Result = NULLREGION;
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NtUserScrollDC
|
|
||||||
*
|
|
||||||
* Status
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL APIENTRY
|
|
||||||
NtUserScrollDC(
|
|
||||||
HDC hDC,
|
|
||||||
INT dx,
|
|
||||||
INT dy,
|
|
||||||
const RECT *prcUnsafeScroll,
|
|
||||||
const RECT *prcUnsafeClip,
|
|
||||||
HRGN hrgnUpdate,
|
|
||||||
LPRECT prcUnsafeUpdate)
|
|
||||||
{
|
|
||||||
DECLARE_RETURN(DWORD);
|
|
||||||
RECTL rcScroll, rcClip, rcUpdate;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
DWORD Result;
|
|
||||||
|
|
||||||
TRACE("Enter NtUserScrollDC\n");
|
|
||||||
UserEnterExclusive();
|
|
||||||
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
|
||||||
if (prcUnsafeScroll)
|
|
||||||
{
|
|
||||||
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
|
|
||||||
rcScroll = *prcUnsafeScroll;
|
|
||||||
}
|
|
||||||
if (prcUnsafeClip)
|
|
||||||
{
|
|
||||||
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
|
|
||||||
rcClip = *prcUnsafeClip;
|
|
||||||
}
|
|
||||||
if (prcUnsafeUpdate)
|
|
||||||
{
|
|
||||||
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
Status = _SEH2_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH2_END
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
SetLastNtError(Status);
|
|
||||||
RETURN(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = UserScrollDC( hDC,
|
|
||||||
dx,
|
|
||||||
dy,
|
|
||||||
prcUnsafeScroll? &rcScroll : 0,
|
|
||||||
prcUnsafeClip? &rcClip : 0,
|
|
||||||
hrgnUpdate,
|
|
||||||
NULL,
|
|
||||||
prcUnsafeUpdate? &rcUpdate : NULL);
|
|
||||||
if(Result == ERROR)
|
|
||||||
{
|
|
||||||
/* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
|
|
||||||
RETURN(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prcUnsafeUpdate)
|
|
||||||
{
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
|
||||||
*prcUnsafeUpdate = rcUpdate;
|
|
||||||
}
|
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
Status = _SEH2_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH2_END
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* FIXME: SetLastError? */
|
|
||||||
/* FIXME: correct? We have already scrolled! */
|
|
||||||
RETURN(FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN(TRUE);
|
|
||||||
|
|
||||||
CLEANUP:
|
|
||||||
TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
|
|
||||||
UserLeave();
|
|
||||||
END_CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NtUserScrollWindowEx
|
|
||||||
*
|
|
||||||
* Status
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
|
|
||||||
DWORD APIENTRY
|
|
||||||
NtUserScrollWindowEx(
|
|
||||||
HWND hWnd,
|
|
||||||
INT dx,
|
|
||||||
INT dy,
|
|
||||||
const RECT *prcUnsafeScroll,
|
|
||||||
const RECT *prcUnsafeClip,
|
|
||||||
HRGN hrgnUpdate,
|
|
||||||
LPRECT prcUnsafeUpdate,
|
|
||||||
UINT flags)
|
|
||||||
{
|
|
||||||
RECTL rcScroll, rcClip, rcCaret, rcUpdate;
|
|
||||||
INT Result;
|
|
||||||
PWND Window = NULL, CaretWnd;
|
|
||||||
HDC hDC;
|
|
||||||
PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
|
|
||||||
HWND hwndCaret;
|
|
||||||
DWORD dcxflags = 0;
|
|
||||||
int rdw_flags;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
DECLARE_RETURN(DWORD);
|
|
||||||
USER_REFERENCE_ENTRY Ref, CaretRef;
|
|
||||||
|
|
||||||
TRACE("Enter NtUserScrollWindowEx\n");
|
|
||||||
UserEnterExclusive();
|
|
||||||
|
|
||||||
Window = UserGetWindowObject(hWnd);
|
|
||||||
if (!Window || !IntIsWindowDrawable(Window))
|
|
||||||
{
|
|
||||||
Window = NULL; /* prevent deref at cleanup */
|
|
||||||
RETURN( ERROR);
|
|
||||||
}
|
|
||||||
UserRefObjectCo(Window, &Ref);
|
|
||||||
|
|
||||||
IntGetClientRect(Window, &rcClip);
|
|
||||||
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
|
||||||
if (prcUnsafeScroll)
|
|
||||||
{
|
|
||||||
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
|
|
||||||
RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rcScroll = rcClip;
|
|
||||||
|
|
||||||
if (prcUnsafeClip)
|
|
||||||
{
|
|
||||||
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
|
|
||||||
RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
Status = _SEH2_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH2_END
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
SetLastNtError(Status);
|
|
||||||
RETURN(ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
|
|
||||||
(dx == 0 && dy == 0))
|
|
||||||
{
|
|
||||||
RETURN(NULLREGION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We must use a copy of the region, as we can't hold an exclusive lock
|
|
||||||
* on it while doing callouts to user-mode */
|
|
||||||
RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
|
|
||||||
if(!RgnUpdate)
|
|
||||||
{
|
|
||||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
RETURN(ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hrgnUpdate)
|
|
||||||
{
|
|
||||||
RgnTemp = REGION_LockRgn(hrgnUpdate);
|
|
||||||
if (!RgnTemp)
|
|
||||||
{
|
|
||||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
|
||||||
RETURN(ERROR);
|
|
||||||
}
|
|
||||||
IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
|
|
||||||
REGION_UnlockRgn(RgnTemp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
|
|
||||||
if (flags & SW_SCROLLWNDDCE)
|
|
||||||
{
|
|
||||||
dcxflags = DCX_USESTYLE;
|
|
||||||
|
|
||||||
if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
|
|
||||||
dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
|
|
||||||
|
|
||||||
if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
|
|
||||||
dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* So in this case ScrollWindowEx uses Cache DC. */
|
|
||||||
dcxflags = DCX_CACHE|DCX_USESTYLE;
|
|
||||||
if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
|
|
||||||
}
|
|
||||||
|
|
||||||
hDC = UserGetDCEx(Window, 0, dcxflags);
|
|
||||||
if (!hDC)
|
|
||||||
{
|
|
||||||
/* FIXME: SetLastError? */
|
|
||||||
RETURN(ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
|
|
||||||
|
|
||||||
rcCaret = rcScroll;
|
|
||||||
hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
|
|
||||||
|
|
||||||
Result = UserScrollDC( hDC,
|
|
||||||
dx,
|
|
||||||
dy,
|
|
||||||
&rcScroll,
|
|
||||||
&rcClip,
|
|
||||||
NULL,
|
|
||||||
RgnUpdate,
|
|
||||||
prcUnsafeUpdate? &rcUpdate : NULL);
|
|
||||||
|
|
||||||
UserReleaseDC(Window, hDC, FALSE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Take into account the fact that some damage may have occurred during
|
|
||||||
* the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
|
|
||||||
*/
|
|
||||||
|
|
||||||
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
|
|
||||||
if (!RgnTemp)
|
|
||||||
{
|
|
||||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
RETURN(ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (co_IntGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
|
|
||||||
{
|
|
||||||
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
|
|
||||||
if (RgnClip)
|
|
||||||
{
|
|
||||||
if (hrgnUpdate)
|
|
||||||
{
|
|
||||||
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
|
|
||||||
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
|
|
||||||
}
|
|
||||||
|
|
||||||
REGION_bOffsetRgn(RgnTemp, dx, dy);
|
|
||||||
|
|
||||||
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
|
|
||||||
|
|
||||||
if (hrgnUpdate)
|
|
||||||
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
|
|
||||||
|
|
||||||
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
|
|
||||||
|
|
||||||
REGION_Delete(RgnClip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
REGION_Delete(RgnTemp);
|
|
||||||
|
|
||||||
if (flags & SW_SCROLLCHILDREN)
|
|
||||||
{
|
|
||||||
PWND Child;
|
|
||||||
RECTL rcChild;
|
|
||||||
POINT ClientOrigin;
|
|
||||||
USER_REFERENCE_ENTRY WndRef;
|
|
||||||
RECTL rcDummy;
|
|
||||||
LPARAM lParam;
|
|
||||||
|
|
||||||
IntGetClientOrigin(Window, &ClientOrigin);
|
|
||||||
|
|
||||||
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
|
|
||||||
{
|
|
||||||
rcChild = Child->rcWindow;
|
|
||||||
rcChild.left -= ClientOrigin.x;
|
|
||||||
rcChild.top -= ClientOrigin.y;
|
|
||||||
rcChild.right -= ClientOrigin.x;
|
|
||||||
rcChild.bottom -= ClientOrigin.y;
|
|
||||||
|
|
||||||
if (!prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
|
|
||||||
{
|
|
||||||
UserRefObjectCo(Child, &WndRef);
|
|
||||||
|
|
||||||
if (Window->spwndParent == UserGetDesktopWindow()) // Window->spwndParent->fnid == FNID_DESKTOP )
|
|
||||||
lParam = MAKELONG(Child->rcClient.left, Child->rcClient.top);
|
|
||||||
else
|
|
||||||
lParam = MAKELONG(rcChild.left + dx, rcChild.top + dy);
|
|
||||||
|
|
||||||
/* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
|
|
||||||
/* windows sometimes a WM_MOVE */
|
|
||||||
co_IntSendMessage(UserHMGetHandle(Child), WM_MOVE, 0, lParam);
|
|
||||||
|
|
||||||
UserDerefObjectCo(Child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & (SW_INVALIDATE | SW_ERASE))
|
|
||||||
{
|
|
||||||
co_UserRedrawWindow( Window,
|
|
||||||
NULL,
|
|
||||||
RgnUpdate,
|
|
||||||
rdw_flags | /* HACK */
|
|
||||||
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : RDW_NOCHILDREN) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
|
|
||||||
{
|
|
||||||
UserRefObjectCo(CaretWnd, &CaretRef);
|
|
||||||
|
|
||||||
co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
|
|
||||||
co_UserShowCaret(CaretWnd);
|
|
||||||
|
|
||||||
UserDerefObjectCo(CaretWnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prcUnsafeUpdate)
|
|
||||||
{
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
|
||||||
/* Probe here, to not fail on invalid pointer before scrolling */
|
|
||||||
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
|
|
||||||
*prcUnsafeUpdate = rcUpdate;
|
|
||||||
}
|
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
Status = _SEH2_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH2_END
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
SetLastNtError(Status);
|
|
||||||
RETURN(ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN(Result);
|
|
||||||
|
|
||||||
CLEANUP:
|
|
||||||
if (hrgnUpdate && (_ret_ != ERROR))
|
|
||||||
{
|
|
||||||
/* Give everything back to the caller */
|
|
||||||
RgnTemp = REGION_LockRgn(hrgnUpdate);
|
|
||||||
/* The handle should still be valid */
|
|
||||||
ASSERT(RgnTemp);
|
|
||||||
if (RgnWinupd)
|
|
||||||
IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
|
|
||||||
else
|
|
||||||
IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
|
|
||||||
REGION_UnlockRgn(RgnTemp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RgnWinupd)
|
|
||||||
{
|
|
||||||
REGION_Delete(RgnWinupd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RgnUpdate)
|
|
||||||
{
|
|
||||||
REGION_Delete(RgnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Window)
|
|
||||||
UserDerefObjectCo(Window);
|
|
||||||
|
|
||||||
TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
|
|
||||||
UserLeave();
|
|
||||||
END_CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
|
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
|
|
|
@ -32,3 +32,5 @@ BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT);
|
||||||
HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);
|
HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);
|
||||||
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND );
|
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND );
|
||||||
BOOL FASTCALL IntFlashWindowEx(PWND,PFLASHWINFO);
|
BOOL FASTCALL IntFlashWindowEx(PWND,PFLASHWINFO);
|
||||||
|
BOOL FASTCALL IntIntersectWithParents(PWND, RECTL *);
|
||||||
|
BOOL FASTCALL IntIsWindowDrawable(PWND);
|
610
reactos/win32ss/user/ntuser/scrollex.c
Normal file
610
reactos/win32ss/user/ntuser/scrollex.c
Normal file
|
@ -0,0 +1,610 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Win32k subsystem
|
||||||
|
* PURPOSE: Window scrolling function
|
||||||
|
* FILE: win32ss/user/ntuser/scrollex.c
|
||||||
|
* PROGRAMER: Filip Navara (xnavara@volny.cz)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <win32k.h>
|
||||||
|
|
||||||
|
DBG_DEFAULT_CHANNEL(UserPainting);
|
||||||
|
|
||||||
|
static
|
||||||
|
HWND FASTCALL
|
||||||
|
co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
|
||||||
|
{
|
||||||
|
PDESKTOP Desktop;
|
||||||
|
PTHRDCARETINFO CaretInfo;
|
||||||
|
PTHREADINFO pti;
|
||||||
|
PUSER_MESSAGE_QUEUE ActiveMessageQueue;
|
||||||
|
HWND hWndCaret;
|
||||||
|
PWND WndCaret;
|
||||||
|
|
||||||
|
ASSERT_REFS_CO(Window);
|
||||||
|
|
||||||
|
pti = PsGetCurrentThreadWin32Thread();
|
||||||
|
Desktop = pti->rpdesk;
|
||||||
|
ActiveMessageQueue = Desktop->ActiveMessageQueue;
|
||||||
|
if (!ActiveMessageQueue) return 0;
|
||||||
|
CaretInfo = ActiveMessageQueue->CaretInfo;
|
||||||
|
hWndCaret = CaretInfo->hWnd;
|
||||||
|
|
||||||
|
WndCaret = ValidateHwndNoErr(hWndCaret);
|
||||||
|
|
||||||
|
// FIXME: Check for WndCaret can be NULL
|
||||||
|
if (WndCaret == Window ||
|
||||||
|
((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
|
||||||
|
{
|
||||||
|
POINT pt, FromOffset, ToOffset;
|
||||||
|
RECTL rcCaret;
|
||||||
|
|
||||||
|
pt.x = CaretInfo->Pos.x;
|
||||||
|
pt.y = CaretInfo->Pos.y;
|
||||||
|
IntGetClientOrigin(WndCaret, &FromOffset);
|
||||||
|
IntGetClientOrigin(Window, &ToOffset);
|
||||||
|
rcCaret.left = pt.x;
|
||||||
|
rcCaret.top = pt.y;
|
||||||
|
rcCaret.right = pt.x + CaretInfo->Size.cx;
|
||||||
|
rcCaret.bottom = pt.y + CaretInfo->Size.cy;
|
||||||
|
if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
|
||||||
|
{
|
||||||
|
co_UserHideCaret(0);
|
||||||
|
lprc->left = pt.x;
|
||||||
|
lprc->top = pt.y;
|
||||||
|
return hWndCaret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Old GetUpdateRgn, for scrolls, see above note.
|
||||||
|
*/
|
||||||
|
INT FASTCALL
|
||||||
|
co_IntGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
|
||||||
|
{
|
||||||
|
int RegionType;
|
||||||
|
RECTL Rect;
|
||||||
|
PREGION UpdateRgn;
|
||||||
|
|
||||||
|
ASSERT_REFS_CO(Window);
|
||||||
|
|
||||||
|
if (bErase)
|
||||||
|
{
|
||||||
|
co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Window->state &= ~WNDS_UPDATEDIRTY;
|
||||||
|
|
||||||
|
if (Window->hrgnUpdate == NULL)
|
||||||
|
{
|
||||||
|
REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
|
||||||
|
return NULLREGION;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateRgn = REGION_LockRgn(Window->hrgnUpdate);
|
||||||
|
if (!UpdateRgn)
|
||||||
|
return ERROR;
|
||||||
|
|
||||||
|
Rect = Window->rcClient;
|
||||||
|
IntIntersectWithParents(Window, &Rect);
|
||||||
|
REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
|
||||||
|
RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
|
||||||
|
REGION_bOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
|
||||||
|
REGION_UnlockRgn(UpdateRgn);
|
||||||
|
|
||||||
|
return RegionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
INT FASTCALL
|
||||||
|
UserScrollDC(
|
||||||
|
HDC hDC,
|
||||||
|
INT dx,
|
||||||
|
INT dy,
|
||||||
|
const RECTL *prcScroll,
|
||||||
|
const RECTL *prcClip,
|
||||||
|
HRGN hrgnUpdate,
|
||||||
|
PREGION RgnUpdate,
|
||||||
|
RECTL *prcUpdate)
|
||||||
|
{
|
||||||
|
PDC pDC;
|
||||||
|
RECTL rcScroll, rcClip, rcSrc, rcDst;
|
||||||
|
INT Result;
|
||||||
|
|
||||||
|
if (GdiGetClipBox(hDC, &rcClip) == ERROR)
|
||||||
|
{
|
||||||
|
ERR("GdiGetClipBox failed for HDC %p\n", hDC);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rcScroll = rcClip;
|
||||||
|
if (prcClip)
|
||||||
|
{
|
||||||
|
RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prcScroll)
|
||||||
|
{
|
||||||
|
rcScroll = *prcScroll;
|
||||||
|
RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rcSrc = rcClip;
|
||||||
|
}
|
||||||
|
|
||||||
|
rcDst = rcSrc;
|
||||||
|
RECTL_vOffsetRect(&rcDst, dx, dy);
|
||||||
|
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
|
||||||
|
|
||||||
|
if (!NtGdiBitBlt( hDC,
|
||||||
|
rcDst.left,
|
||||||
|
rcDst.top,
|
||||||
|
rcDst.right - rcDst.left,
|
||||||
|
rcDst.bottom - rcDst.top,
|
||||||
|
hDC,
|
||||||
|
rcDst.left - dx,
|
||||||
|
rcDst.top - dy,
|
||||||
|
SRCCOPY,
|
||||||
|
0,
|
||||||
|
0))
|
||||||
|
{
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the region that was invalidated by moving or
|
||||||
|
could not be copied, because it was not visible */
|
||||||
|
if (RgnUpdate || hrgnUpdate || prcUpdate)
|
||||||
|
{
|
||||||
|
PREGION RgnOwn, RgnTmp;
|
||||||
|
|
||||||
|
pDC = DC_LockDc(hDC);
|
||||||
|
if (!pDC)
|
||||||
|
{
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hrgnUpdate)
|
||||||
|
{
|
||||||
|
NT_ASSERT(RgnUpdate == NULL);
|
||||||
|
RgnUpdate = REGION_LockRgn(hrgnUpdate);
|
||||||
|
if (!RgnUpdate)
|
||||||
|
{
|
||||||
|
DC_UnlockDc(pDC);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Begin with the shifted and then clipped scroll rect */
|
||||||
|
rcDst = rcScroll;
|
||||||
|
RECTL_vOffsetRect(&rcDst, dx, dy);
|
||||||
|
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
|
||||||
|
if (RgnUpdate)
|
||||||
|
{
|
||||||
|
RgnOwn = RgnUpdate;
|
||||||
|
REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the source rect */
|
||||||
|
RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
|
||||||
|
IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
|
||||||
|
|
||||||
|
/* Substract the part of the dest that was visible in source */
|
||||||
|
IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
|
||||||
|
REGION_bOffsetRgn(RgnTmp, dx, dy);
|
||||||
|
Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
|
||||||
|
|
||||||
|
/* DO NOT Unlock DC while messing with prgnVis! */
|
||||||
|
DC_UnlockDc(pDC);
|
||||||
|
|
||||||
|
REGION_Delete(RgnTmp);
|
||||||
|
|
||||||
|
if (prcUpdate)
|
||||||
|
{
|
||||||
|
REGION_GetRgnBox(RgnOwn, prcUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hrgnUpdate)
|
||||||
|
{
|
||||||
|
REGION_UnlockRgn(RgnUpdate);
|
||||||
|
}
|
||||||
|
else if (!RgnUpdate)
|
||||||
|
{
|
||||||
|
REGION_Delete(RgnOwn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Result = NULLREGION;
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NtUserScrollDC
|
||||||
|
*
|
||||||
|
* Status
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOL APIENTRY
|
||||||
|
NtUserScrollDC(
|
||||||
|
HDC hDC,
|
||||||
|
INT dx,
|
||||||
|
INT dy,
|
||||||
|
const RECT *prcUnsafeScroll,
|
||||||
|
const RECT *prcUnsafeClip,
|
||||||
|
HRGN hrgnUpdate,
|
||||||
|
LPRECT prcUnsafeUpdate)
|
||||||
|
{
|
||||||
|
DECLARE_RETURN(DWORD);
|
||||||
|
RECTL rcScroll, rcClip, rcUpdate;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
DWORD Result;
|
||||||
|
|
||||||
|
TRACE("Enter NtUserScrollDC\n");
|
||||||
|
UserEnterExclusive();
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
if (prcUnsafeScroll)
|
||||||
|
{
|
||||||
|
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
|
||||||
|
rcScroll = *prcUnsafeScroll;
|
||||||
|
}
|
||||||
|
if (prcUnsafeClip)
|
||||||
|
{
|
||||||
|
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
|
||||||
|
rcClip = *prcUnsafeClip;
|
||||||
|
}
|
||||||
|
if (prcUnsafeUpdate)
|
||||||
|
{
|
||||||
|
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
SetLastNtError(Status);
|
||||||
|
RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = UserScrollDC( hDC,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
prcUnsafeScroll? &rcScroll : 0,
|
||||||
|
prcUnsafeClip? &rcClip : 0,
|
||||||
|
hrgnUpdate,
|
||||||
|
NULL,
|
||||||
|
prcUnsafeUpdate? &rcUpdate : NULL);
|
||||||
|
if(Result == ERROR)
|
||||||
|
{
|
||||||
|
/* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
|
||||||
|
RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prcUnsafeUpdate)
|
||||||
|
{
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
*prcUnsafeUpdate = rcUpdate;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* FIXME: SetLastError? */
|
||||||
|
/* FIXME: correct? We have already scrolled! */
|
||||||
|
RETURN(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN(TRUE);
|
||||||
|
|
||||||
|
CLEANUP:
|
||||||
|
TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
|
||||||
|
UserLeave();
|
||||||
|
END_CLEANUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NtUserScrollWindowEx
|
||||||
|
*
|
||||||
|
* Status
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
|
||||||
|
DWORD APIENTRY
|
||||||
|
NtUserScrollWindowEx(
|
||||||
|
HWND hWnd,
|
||||||
|
INT dx,
|
||||||
|
INT dy,
|
||||||
|
const RECT *prcUnsafeScroll,
|
||||||
|
const RECT *prcUnsafeClip,
|
||||||
|
HRGN hrgnUpdate,
|
||||||
|
LPRECT prcUnsafeUpdate,
|
||||||
|
UINT flags)
|
||||||
|
{
|
||||||
|
RECTL rcScroll, rcClip, rcCaret, rcUpdate;
|
||||||
|
INT Result;
|
||||||
|
PWND Window = NULL, CaretWnd;
|
||||||
|
HDC hDC;
|
||||||
|
PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
|
||||||
|
HWND hwndCaret;
|
||||||
|
DWORD dcxflags = 0;
|
||||||
|
int rdw_flags;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
DECLARE_RETURN(DWORD);
|
||||||
|
USER_REFERENCE_ENTRY Ref, CaretRef;
|
||||||
|
|
||||||
|
TRACE("Enter NtUserScrollWindowEx\n");
|
||||||
|
UserEnterExclusive();
|
||||||
|
|
||||||
|
Window = UserGetWindowObject(hWnd);
|
||||||
|
if (!Window || !IntIsWindowDrawable(Window))
|
||||||
|
{
|
||||||
|
Window = NULL; /* prevent deref at cleanup */
|
||||||
|
RETURN( ERROR);
|
||||||
|
}
|
||||||
|
UserRefObjectCo(Window, &Ref);
|
||||||
|
|
||||||
|
IntGetClientRect(Window, &rcClip);
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
if (prcUnsafeScroll)
|
||||||
|
{
|
||||||
|
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
|
||||||
|
RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rcScroll = rcClip;
|
||||||
|
|
||||||
|
if (prcUnsafeClip)
|
||||||
|
{
|
||||||
|
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
|
||||||
|
RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
SetLastNtError(Status);
|
||||||
|
RETURN(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
|
||||||
|
(dx == 0 && dy == 0))
|
||||||
|
{
|
||||||
|
RETURN(NULLREGION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must use a copy of the region, as we can't hold an exclusive lock
|
||||||
|
* on it while doing callouts to user-mode */
|
||||||
|
RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
|
||||||
|
if(!RgnUpdate)
|
||||||
|
{
|
||||||
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
RETURN(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hrgnUpdate)
|
||||||
|
{
|
||||||
|
RgnTemp = REGION_LockRgn(hrgnUpdate);
|
||||||
|
if (!RgnTemp)
|
||||||
|
{
|
||||||
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
RETURN(ERROR);
|
||||||
|
}
|
||||||
|
IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
|
||||||
|
REGION_UnlockRgn(RgnTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
|
||||||
|
if (flags & SW_SCROLLWNDDCE)
|
||||||
|
{
|
||||||
|
dcxflags = DCX_USESTYLE;
|
||||||
|
|
||||||
|
if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
|
||||||
|
dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
|
||||||
|
|
||||||
|
if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
|
||||||
|
dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* So in this case ScrollWindowEx uses Cache DC. */
|
||||||
|
dcxflags = DCX_CACHE|DCX_USESTYLE;
|
||||||
|
if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
|
||||||
|
}
|
||||||
|
|
||||||
|
hDC = UserGetDCEx(Window, 0, dcxflags);
|
||||||
|
if (!hDC)
|
||||||
|
{
|
||||||
|
/* FIXME: SetLastError? */
|
||||||
|
RETURN(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
|
||||||
|
|
||||||
|
rcCaret = rcScroll;
|
||||||
|
hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
|
||||||
|
|
||||||
|
Result = UserScrollDC( hDC,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
&rcScroll,
|
||||||
|
&rcClip,
|
||||||
|
NULL,
|
||||||
|
RgnUpdate,
|
||||||
|
prcUnsafeUpdate? &rcUpdate : NULL);
|
||||||
|
|
||||||
|
UserReleaseDC(Window, hDC, FALSE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take into account the fact that some damage may have occurred during
|
||||||
|
* the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
|
||||||
|
*/
|
||||||
|
|
||||||
|
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
|
||||||
|
if (!RgnTemp)
|
||||||
|
{
|
||||||
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
RETURN(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (co_IntGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
|
||||||
|
{
|
||||||
|
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
|
||||||
|
if (RgnClip)
|
||||||
|
{
|
||||||
|
if (hrgnUpdate)
|
||||||
|
{
|
||||||
|
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
|
||||||
|
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGION_bOffsetRgn(RgnTemp, dx, dy);
|
||||||
|
|
||||||
|
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
|
||||||
|
|
||||||
|
if (hrgnUpdate)
|
||||||
|
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
|
||||||
|
|
||||||
|
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
|
||||||
|
|
||||||
|
REGION_Delete(RgnClip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
REGION_Delete(RgnTemp);
|
||||||
|
|
||||||
|
if (flags & SW_SCROLLCHILDREN)
|
||||||
|
{
|
||||||
|
PWND Child;
|
||||||
|
RECTL rcChild;
|
||||||
|
POINT ClientOrigin;
|
||||||
|
USER_REFERENCE_ENTRY WndRef;
|
||||||
|
RECTL rcDummy;
|
||||||
|
LPARAM lParam;
|
||||||
|
|
||||||
|
IntGetClientOrigin(Window, &ClientOrigin);
|
||||||
|
|
||||||
|
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
|
||||||
|
{
|
||||||
|
rcChild = Child->rcWindow;
|
||||||
|
rcChild.left -= ClientOrigin.x;
|
||||||
|
rcChild.top -= ClientOrigin.y;
|
||||||
|
rcChild.right -= ClientOrigin.x;
|
||||||
|
rcChild.bottom -= ClientOrigin.y;
|
||||||
|
|
||||||
|
if (!prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
|
||||||
|
{
|
||||||
|
UserRefObjectCo(Child, &WndRef);
|
||||||
|
|
||||||
|
if (Window->spwndParent == UserGetDesktopWindow()) // Window->spwndParent->fnid == FNID_DESKTOP )
|
||||||
|
lParam = MAKELONG(Child->rcClient.left, Child->rcClient.top);
|
||||||
|
else
|
||||||
|
lParam = MAKELONG(rcChild.left + dx, rcChild.top + dy);
|
||||||
|
|
||||||
|
/* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
|
||||||
|
/* windows sometimes a WM_MOVE */
|
||||||
|
co_IntSendMessage(UserHMGetHandle(Child), WM_MOVE, 0, lParam);
|
||||||
|
|
||||||
|
UserDerefObjectCo(Child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & (SW_INVALIDATE | SW_ERASE))
|
||||||
|
{
|
||||||
|
co_UserRedrawWindow( Window,
|
||||||
|
NULL,
|
||||||
|
RgnUpdate,
|
||||||
|
rdw_flags | /* HACK */
|
||||||
|
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : RDW_NOCHILDREN) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
|
||||||
|
{
|
||||||
|
UserRefObjectCo(CaretWnd, &CaretRef);
|
||||||
|
|
||||||
|
co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
|
||||||
|
co_UserShowCaret(CaretWnd);
|
||||||
|
|
||||||
|
UserDerefObjectCo(CaretWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prcUnsafeUpdate)
|
||||||
|
{
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
/* Probe here, to not fail on invalid pointer before scrolling */
|
||||||
|
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
|
||||||
|
*prcUnsafeUpdate = rcUpdate;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
SetLastNtError(Status);
|
||||||
|
RETURN(ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN(Result);
|
||||||
|
|
||||||
|
CLEANUP:
|
||||||
|
if (hrgnUpdate && (_ret_ != ERROR))
|
||||||
|
{
|
||||||
|
/* Give everything back to the caller */
|
||||||
|
RgnTemp = REGION_LockRgn(hrgnUpdate);
|
||||||
|
/* The handle should still be valid */
|
||||||
|
ASSERT(RgnTemp);
|
||||||
|
if (RgnWinupd)
|
||||||
|
IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
|
||||||
|
else
|
||||||
|
IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
|
||||||
|
REGION_UnlockRgn(RgnTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RgnWinupd)
|
||||||
|
{
|
||||||
|
REGION_Delete(RgnWinupd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RgnUpdate)
|
||||||
|
{
|
||||||
|
REGION_Delete(RgnUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Window)
|
||||||
|
UserDerefObjectCo(Window);
|
||||||
|
|
||||||
|
TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
|
||||||
|
UserLeave();
|
||||||
|
END_CLEANUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* EOF */
|
|
@ -123,7 +123,10 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu);
|
||||||
|
|
||||||
/*************** SCROLLBAR.C ***************/
|
/*************** SCROLLBAR.C ***************/
|
||||||
|
|
||||||
DWORD FASTCALL
|
DWORD FASTCALL co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
|
||||||
co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
|
|
||||||
|
/************** NONCLIENT **************/
|
||||||
|
|
||||||
|
VOID FASTCALL DefWndDoSizeMove(PWND pwnd, WORD wParam);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue