- Start ordering functions into separate files.
svn path=/trunk/; revision=68582
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
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)
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().
//
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 */
--- /dev/null
+/*
+ * 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 */
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(
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
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
--- /dev/null
+/*
+ * 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 */
/*************** 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 */