mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 18:42:14 +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/mouse.c
|
||||
user/ntuser/msgqueue.c
|
||||
user/ntuser/nonclient.c
|
||||
user/ntuser/ntstubs.c
|
||||
user/ntuser/ntuser.c
|
||||
user/ntuser/painting.c
|
||||
user/ntuser/prop.c
|
||||
user/ntuser/scrollbar.c
|
||||
user/ntuser/scrollex.c
|
||||
user/ntuser/session.c
|
||||
user/ntuser/shutdown.c
|
||||
user/ntuser/simplecall.c
|
||||
|
|
|
@ -11,25 +11,6 @@
|
|||
|
||||
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
|
||||
DefWndControlColor(HDC hDC, UINT ctlType)
|
||||
|
@ -119,538 +100,6 @@ DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos)
|
|||
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().
|
||||
//
|
||||
|
@ -1197,230 +646,4 @@ IntDefWindowProc(
|
|||
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 */
|
||||
|
|
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;
|
||||
}
|
||||
|
||||
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
|
||||
FASTCALL
|
||||
IntPrintWindow(
|
||||
|
@ -1914,553 +1865,6 @@ 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};
|
||||
|
||||
BOOL
|
||||
|
|
|
@ -32,3 +32,5 @@ BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT);
|
|||
HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);
|
||||
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND );
|
||||
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 ***************/
|
||||
|
||||
DWORD FASTCALL
|
||||
co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
|
||||
DWORD FASTCALL co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
|
||||
|
||||
/************** NONCLIENT **************/
|
||||
|
||||
VOID FASTCALL DefWndDoSizeMove(PWND pwnd, WORD wParam);
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue