/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Win32k subsystem * PURPOSE: Miscellaneous User functions * FILE: subsystems/win32/win32k/ntuser/defwnd.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)) // Client Shutdown messages #define MCS_SHUTDOWNTIMERS 1 #define MCS_QUERYENDSESSION 2 // Client Shutdown returns #define MCSR_GOODFORSHUTDOWN 1 #define MCSR_SHUTDOWNFINISHED 2 #define MCSR_DONOTSHUTDOWN 3 /* * Based on CSRSS and described in pages 1115 - 1118 "Windows Internals, Fifth Edition". * Apparently CSRSS sends out messages to do this w/o going into win32k internals. */ static LRESULT FASTCALL IntClientShutdown( PWND pWindow, WPARAM wParam, LPARAM lParam ) { LPARAM lParams; BOOL KillTimers; INT i; LRESULT lResult = MCSR_GOODFORSHUTDOWN; HWND *List; lParams = wParam & (ENDSESSION_LOGOFF|ENDSESSION_CRITICAL|ENDSESSION_CLOSEAPP); KillTimers = wParam & MCS_SHUTDOWNTIMERS ? TRUE : FALSE; /* First, send end sessions to children. */ List = IntWinListChildren(pWindow); if (List) { for (i = 0; List[i]; i++) { PWND WndChild; if (!(WndChild = UserGetWindowObject(List[i]))) continue; if (wParam & MCS_QUERYENDSESSION) { if (!co_IntSendMessage(WndChild->head.h, WM_QUERYENDSESSION, 0, lParams)) { lResult = MCSR_DONOTSHUTDOWN; break; } } else { co_IntSendMessage(WndChild->head.h, WM_ENDSESSION, KillTimers, lParams); if (KillTimers) { DestroyTimersForWindow(WndChild->head.pti, WndChild); } lResult = MCSR_SHUTDOWNFINISHED; } } ExFreePoolWithTag(List, USERTAG_WINDOWLIST); } if (List && (lResult == MCSR_DONOTSHUTDOWN)) return lResult; /* Send to the caller. */ if (wParam & MCS_QUERYENDSESSION) { if (!co_IntSendMessage(pWindow->head.h, WM_QUERYENDSESSION, 0, lParams)) { lResult = MCSR_DONOTSHUTDOWN; } } else { co_IntSendMessage(pWindow->head.h, WM_ENDSESSION, KillTimers, lParams); if (KillTimers) { DestroyTimersForWindow(pWindow->head.pti, pWindow); } lResult = MCSR_SHUTDOWNFINISHED; } return lResult; } HBRUSH FASTCALL DefWndControlColor(HDC hDC, UINT ctlType) { if (ctlType == CTLCOLOR_SCROLLBAR) { HBRUSH hb = IntGetSysColorBrush(COLOR_SCROLLBAR); COLORREF bk = IntGetSysColor(COLOR_3DHILIGHT); IntGdiSetTextColor(hDC, IntGetSysColor(COLOR_3DFACE)); IntGdiSetBkColor(hDC, bk); /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT * we better use 0x55aa bitmap brush to make scrollbar's background * look different from the window background. */ if ( bk == IntGetSysColor(COLOR_WINDOW)) return gpsi->hbrGray; NtGdiUnrealizeObject( hb ); return hb; } IntGdiSetTextColor(hDC, IntGetSysColor(COLOR_WINDOWTEXT)); if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX)) { IntGdiSetBkColor(hDC, IntGetSysColor(COLOR_WINDOW)); } else { IntGdiSetBkColor(hDC, IntGetSysColor(COLOR_3DFACE)); return IntGetSysColorBrush(COLOR_3DFACE); } return IntGetSysColorBrush(COLOR_WINDOW); } LRESULT FASTCALL DefWndHandleWindowPosChanging(PWND pWnd, WINDOWPOS* Pos) { POINT maxTrack, minTrack; LONG style = pWnd->style; if (Pos->flags & SWP_NOSIZE) return 0; if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0)) { co_WinPosGetMinMaxInfo(pWnd, NULL, NULL, &minTrack, &maxTrack); Pos->cx = min(Pos->cx, maxTrack.x); Pos->cy = min(Pos->cy, maxTrack.y); if (!(style & WS_MINIMIZE)) { if (Pos->cx < minTrack.x) Pos->cx = minTrack.x; if (Pos->cy < minTrack.y) Pos->cy = minTrack.y; } } else { Pos->cx = max(Pos->cx, 0); Pos->cy = max(Pos->cy, 0); } return 0; } LRESULT FASTCALL DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos) { RECT Rect; LONG style = pWnd->style; IntGetClientRect(pWnd, &Rect); IntMapWindowPoints(pWnd, (style & WS_CHILD ? IntGetParent(pWnd) : NULL), (LPPOINT) &Rect, 2); if (!(Pos->flags & SWP_NOCLIENTMOVE)) { co_IntSendMessage(UserHMGetHandle(pWnd), WM_MOVE, 0, MAKELONG(Rect.left, Rect.top)); } if (!(Pos->flags & SWP_NOCLIENTSIZE) || (Pos->flags & SWP_STATECHANGED)) { if (style & WS_MINIMIZE) co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, SIZE_MINIMIZED, 0 ); else { WPARAM wp = (style & WS_MAXIMIZE) ? SIZE_MAXIMIZED : SIZE_RESTORED; co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, wp, MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top)); } } 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, -height, PATINVERT ); NtGdiPatBlt( hdc, rect->right - 1, rect->top, -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); HCURSOR hDragCursor = 0, hOldCursor = 0; 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 ) /* create a cursor for dragging */ { hDragCursor = pwnd->pcls->hIcon;; if ( !hDragCursor ) hDragCursor = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 ); if ( !hDragCursor ) 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 */ { hOldCursor = IntSetCursor(hDragCursor); 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 ); IntSetCursor( hOldCursor ); } IntDestroyCursor( hDragCursor, FALSE ); } 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(). // LRESULT FASTCALL DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam) { LRESULT lResult = 0; BOOL Hook = FALSE; if (ISITHOOKED(WH_CBT) || (pWnd->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT))) { Hook = TRUE; lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam); if (lResult) return lResult; } switch (wParam & 0xfff0) { case SC_MOVE: case SC_SIZE: DefWndDoSizeMove(pWnd, wParam); break; case SC_MINIMIZE: if (UserHMGetHandle(pWnd) == UserGetActiveWindow()) IntShowOwnedPopups(pWnd,FALSE); // This is done in ShowWindow! Need to retest! co_WinPosShowWindow( pWnd, SW_MINIMIZE ); break; case SC_MAXIMIZE: if (((pWnd->style & WS_MINIMIZE) != 0) && UserHMGetHandle(pWnd) == UserGetActiveWindow()) IntShowOwnedPopups(pWnd,TRUE); co_WinPosShowWindow( pWnd, SW_MAXIMIZE ); break; case SC_RESTORE: if (((pWnd->style & WS_MINIMIZE) != 0) && UserHMGetHandle(pWnd) == UserGetActiveWindow()) IntShowOwnedPopups(pWnd,TRUE); co_WinPosShowWindow( pWnd, SW_RESTORE ); break; case SC_CLOSE: return co_IntSendMessage(UserHMGetHandle(pWnd), WM_CLOSE, 0, 0); case SC_SCREENSAVE: ERR("Screensaver Called!\n"); UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); // always lParam 0 == not Secure break; case SC_HOTKEY: { USER_REFERENCE_ENTRY Ref; pWnd = ValidateHwndNoErr((HWND)lParam); if (pWnd) { if (pWnd->spwndLastActive) { pWnd = pWnd->spwndLastActive; } UserRefObjectCo(pWnd, &Ref); co_IntSetForegroundWindow(pWnd); UserDerefObjectCo(pWnd); if (pWnd->style & WS_MINIMIZE) { UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_RESTORE, 0); } } } break; default: // We do not support anything else here so we should return normal even when sending a hook. return 0; } return(Hook ? 1 : 0); // Don't call us again from user space. } VOID FASTCALL DefWndPrint( PWND pwnd, HDC hdc, ULONG uFlags) { /* * Visibility flag. */ if ( (uFlags & PRF_CHECKVISIBLE) && !IntIsWindowVisible(pwnd) ) return; /* * Unimplemented flags. */ if ( (uFlags & PRF_CHILDREN) || (uFlags & PRF_OWNED) || (uFlags & PRF_NONCLIENT) ) { FIXME("WM_PRINT message with unsupported flags\n"); } /* * Background */ if ( uFlags & PRF_ERASEBKGND) co_IntSendMessage(UserHMGetHandle(pwnd), WM_ERASEBKGND, (WPARAM)hdc, 0); /* * Client area */ if ( uFlags & PRF_CLIENT) co_IntSendMessage(UserHMGetHandle(pwnd), WM_PRINTCLIENT, (WPARAM)hdc, uFlags); } /* Win32k counterpart of User DefWindowProc */ LRESULT FASTCALL IntDefWindowProc( PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi) { LRESULT lResult = 0; USER_REFERENCE_ENTRY Ref; if (Msg > WM_USER) return 0; switch (Msg) { case WM_SYSCOMMAND: { ERR("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam ); lResult = DefWndHandleSysCommand(Wnd, wParam, lParam); break; } case WM_SHOWWINDOW: { if ((Wnd->style & WS_VISIBLE) && wParam) break; if (!(Wnd->style & WS_VISIBLE) && !wParam) break; if (!Wnd->spwndOwner) break; if (LOWORD(lParam)) { if (wParam) { if (!(Wnd->state & WNDS_HIDDENPOPUP)) break; Wnd->state &= ~WNDS_HIDDENPOPUP; } else Wnd->state |= WNDS_HIDDENPOPUP; co_WinPosShowWindow(Wnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE); } } break; case WM_CLIENTSHUTDOWN: return IntClientShutdown(Wnd, wParam, lParam); case WM_APPCOMMAND: ERR("WM_APPCOMMAND\n"); if ( (Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && Wnd != co_GetDesktopWindow(Wnd) ) { if (!co_HOOK_CallHooks(WH_SHELL, HSHELL_APPCOMMAND, wParam, lParam)) co_IntShellHookNotify(HSHELL_APPCOMMAND, wParam, lParam); break; } UserRefObjectCo(Wnd->spwndParent, &Ref); lResult = co_IntSendMessage(UserHMGetHandle(Wnd->spwndParent), WM_APPCOMMAND, wParam, lParam); UserDerefObjectCo(Wnd->spwndParent); break; case WM_CLOSE: co_UserDestroyWindow(Wnd); break; case WM_CTLCOLORMSGBOX: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: case WM_CTLCOLORSCROLLBAR: return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX); case WM_CTLCOLOR: return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam)); case WM_ACTIVATE: /* The default action in Windows is to set the keyboard focus to * the window, if it's being activated and not minimized */ if (LOWORD(wParam) != WA_INACTIVE && !(Wnd->style & WS_MINIMIZE)) { //ERR("WM_ACTIVATE %p\n",hWnd); co_UserSetFocus(Wnd); } break; case WM_MOUSEWHEEL: if (Wnd->style & WS_CHILD) { HWND hwndParent; PWND pwndParent = IntGetParent(Wnd); hwndParent = pwndParent ? UserHMGetHandle(pwndParent) : NULL; return co_IntSendMessage( hwndParent, WM_MOUSEWHEEL, wParam, lParam); } break; case WM_ERASEBKGND: case WM_ICONERASEBKGND: { RECT Rect; HBRUSH hBrush = Wnd->pcls->hbrBackground; if (!hBrush) return 0; if (hBrush <= (HBRUSH)COLOR_MENUBAR) { hBrush = IntGetSysColorBrush((INT)hBrush); } if (Wnd->pcls->style & CS_PARENTDC) { /* can't use GetClipBox with a parent DC or we fill the whole parent */ IntGetClientRect(Wnd, &Rect); GreDPtoLP((HDC)wParam, (LPPOINT)&Rect, 2); } else { GdiGetClipBox((HDC)wParam, &Rect); } FillRect((HDC)wParam, &Rect, hBrush); return (1); } case WM_GETHOTKEY: //ERR("WM_GETHOTKEY\n"); return DefWndGetHotKey(Wnd); case WM_SETHOTKEY: //ERR("WM_SETHOTKEY\n"); return DefWndSetHotKey(Wnd, wParam); case WM_NCHITTEST: { POINT Point; Point.x = GET_X_LPARAM(lParam); Point.y = GET_Y_LPARAM(lParam); return GetNCHitEx(Wnd, Point); } case WM_PRINT: { DefWndPrint(Wnd, (HDC)wParam, lParam); return (0); } case WM_PAINTICON: case WM_PAINT: { PAINTSTRUCT Ps; HDC hDC; /* If already in Paint and Client area is not empty just return. */ if (Wnd->state2 & WNDS2_STARTPAINT && !RECTL_bIsEmptyRect(&Wnd->rcClient)) { ERR("In Paint and Client area is not empty!\n"); return 0; } hDC = IntBeginPaint(Wnd, &Ps); if (hDC) { HICON hIcon; if (((Wnd->style & WS_MINIMIZE) != 0) && (hIcon = Wnd->pcls->hIcon)) { RECT ClientRect; INT x, y; PCURICON_OBJECT pIcon; if (!(pIcon = UserGetCurIconObject(hIcon))) return 0; ERR("Doing Paint and Client area is empty!\n"); IntGetClientRect(Wnd, &ClientRect); x = (ClientRect.right - ClientRect.left - UserGetSystemMetrics(SM_CXICON)) / 2; y = (ClientRect.bottom - ClientRect.top - UserGetSystemMetrics(SM_CYICON)) / 2; UserDrawIconEx( hDC, x, y, pIcon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE ); } IntEndPaint(Wnd, &Ps); } return (0); } case WM_SYNCPAINT: { HRGN hRgn; Wnd->state &= ~WNDS_SYNCPAINTPENDING; ERR("WM_SYNCPAINT\n"); hRgn = IntSysCreateRectRgn(0, 0, 0, 0); if (co_UserGetUpdateRgn(Wnd, hRgn, FALSE) != NULLREGION) { if (!wParam) wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); co_UserRedrawWindow(Wnd, NULL, hRgn, wParam); } GreDeleteObject(hRgn); return 0; } case WM_SETREDRAW: ERR("WM_SETREDRAW\n"); if (wParam) { if (!(Wnd->style & WS_VISIBLE)) { IntSetStyle( Wnd, WS_VISIBLE, 0 ); Wnd->state |= WNDS_SENDNCPAINT; } } else { if (Wnd->style & WS_VISIBLE) { co_UserRedrawWindow( Wnd, NULL, NULL, RDW_ALLCHILDREN | RDW_VALIDATE ); IntSetStyle( Wnd, 0, WS_VISIBLE ); } } return 0; case WM_WINDOWPOSCHANGING: { return (DefWndHandleWindowPosChanging(Wnd, (WINDOWPOS*)lParam)); } case WM_WINDOWPOSCHANGED: { return (DefWndHandleWindowPosChanged(Wnd, (WINDOWPOS*)lParam)); } /* ReactOS only. */ case WM_CBT: { switch (wParam) { case HCBT_MOVESIZE: { RECTL rt; if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(RECT), 1); RtlCopyMemory(&rt, (PVOID)lParam, sizeof(RECT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { lResult = 1; } _SEH2_END; } if (!lResult) lResult = co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)Wnd->head.h, lParam ? (LPARAM)&rt : 0); } break; } break; } break; } return lResult; } HICON FASTCALL NC_IconForWindow( PWND pWnd ) { HICON hIcon = 0; // First thing to do, init the Window Logo icons. if (!gpsi->hIconSmWindows) co_IntSetWndIcons(); if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp); if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp); if (!hIcon) hIcon = pWnd->pcls->hIconSm; if (!hIcon) hIcon = pWnd->pcls->hIcon; if (!hIcon && pWnd->style & DS_MODALFRAME) { if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size. } return hIcon; } 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 */