From: James Tabor Date: Thu, 30 Jul 2015 07:49:09 +0000 (+0000) Subject: [Win32SS] X-Git-Tag: ReactOS-0.4.0~1442 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=6fe69964e1a1ac44be0a29e508291e8a37d8fe45 [Win32SS] - Start ordering functions into separate files. svn path=/trunk/; revision=68582 --- diff --git a/reactos/win32ss/CMakeLists.txt b/reactos/win32ss/CMakeLists.txt index f933547bb84..24477f2dab9 100644 --- a/reactos/win32ss/CMakeLists.txt +++ b/reactos/win32ss/CMakeLists.txt @@ -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 diff --git a/reactos/win32ss/user/ntuser/defwnd.c b/reactos/win32ss/user/ntuser/defwnd.c index 579d2d9aed7..410019add69 100644 --- a/reactos/win32ss/user/ntuser/defwnd.c +++ b/reactos/win32ss/user/ntuser/defwnd.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 */ diff --git a/reactos/win32ss/user/ntuser/nonclient.c b/reactos/win32ss/user/ntuser/nonclient.c new file mode 100644 index 00000000000..6a10bab5512 --- /dev/null +++ b/reactos/win32ss/user/ntuser/nonclient.c @@ -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 +#include + +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 */ diff --git a/reactos/win32ss/user/ntuser/painting.c b/reactos/win32ss/user/ntuser/painting.c index 7f86ccd143a..a79c1306f19 100644 --- a/reactos/win32ss/user/ntuser/painting.c +++ b/reactos/win32ss/user/ntuser/painting.c @@ -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 diff --git a/reactos/win32ss/user/ntuser/painting.h b/reactos/win32ss/user/ntuser/painting.h index c212d6f23b3..307ddbda5c8 100644 --- a/reactos/win32ss/user/ntuser/painting.h +++ b/reactos/win32ss/user/ntuser/painting.h @@ -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); \ No newline at end of file diff --git a/reactos/win32ss/user/ntuser/scrollex.c b/reactos/win32ss/user/ntuser/scrollex.c new file mode 100644 index 00000000000..e0cd6359c69 --- /dev/null +++ b/reactos/win32ss/user/ntuser/scrollex.c @@ -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 + +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 */ diff --git a/reactos/win32ss/user/ntuser/userfuncs.h b/reactos/win32ss/user/ntuser/userfuncs.h index d46911df690..2f0e3869a7a 100644 --- a/reactos/win32ss/user/ntuser/userfuncs.h +++ b/reactos/win32ss/user/ntuser/userfuncs.h @@ -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 */