UINT APIENTRY IntAnimatePalette(HPALETTE hPal, UINT StartIndex, UINT NumEntries, CONST PPALETTEENTRY PaletteColors) { UINT ret = 0; if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) ) { PPALETTE palPtr; UINT pal_entries; HDC hDC; PDC dc; PWND Wnd; const PALETTEENTRY *pptr = PaletteColors; palPtr = PALETTE_ShareLockPalette(hPal); if (!palPtr) return FALSE; pal_entries = palPtr->NumColors; if (StartIndex >= pal_entries) { PALETTE_ShareUnlockPalette(palPtr); return FALSE; } if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex; for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) { /* According to MSDN, only animate PC_RESERVED colours */ if (palPtr->IndexedColors[StartIndex].peFlags & PC_RESERVED) { memcpy( &palPtr->IndexedColors[StartIndex], pptr, sizeof(PALETTEENTRY) ); ret++; PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1); } } PALETTE_ShareUnlockPalette(palPtr); /* Immediately apply the new palette if current window uses it */ Wnd = UserGetDesktopWindow(); hDC = UserGetWindowDC(Wnd); dc = DC_LockDc(hDC); if (NULL != dc) { if (dc->dclevel.hpal == hPal) { DC_UnlockDc(dc); IntGdiRealizePalette(hDC); } else DC_UnlockDc(dc); } UserReleaseDC(Wnd,hDC, FALSE); } return ret; }
BOOL FASTCALL co_IntMouseActivateWindow(PWND Wnd) { HWND Top; USER_REFERENCE_ENTRY Ref; ASSERT_REFS_CO(Wnd); if (Wnd->style & WS_DISABLED) { BOOL Ret; PWND TopWnd; PWND DesktopWindow = UserGetDesktopWindow(); if (DesktopWindow) { ERR("Window Diabled\n"); Top = IntFindChildWindowToOwner(DesktopWindow, Wnd); if ((TopWnd = ValidateHwndNoErr(Top))) { UserRefObjectCo(TopWnd, &Ref); Ret = co_IntMouseActivateWindow(TopWnd); UserDerefObjectCo(TopWnd); return Ret; } } return FALSE; } TRACE("Mouse Active\n"); co_IntSetForegroundAndFocusWindow(Wnd, TRUE); return TRUE; }
BOOL APIENTRY UserClipCursor( RECTL *prcl) { /* FIXME: Check if process has WINSTA_WRITEATTRIBUTES */ PSYSTEM_CURSORINFO CurInfo; PWND DesktopWindow = NULL; CurInfo = IntGetSysCursorInfo(); DesktopWindow = UserGetDesktopWindow(); if (prcl != NULL && DesktopWindow != NULL) { if (prcl->right < prcl->left || prcl->bottom < prcl->top) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } CurInfo->bClipped = TRUE; /* Set nw cliping region. Note: we can't use RECTL_bIntersectRect because it sets rect to 0 0 0 0 when it's empty. For more info see monitor winetest */ CurInfo->rcClip.left = max(prcl->left, DesktopWindow->rcWindow.left); CurInfo->rcClip.right = min(prcl->right, DesktopWindow->rcWindow.right); if (CurInfo->rcClip.right < CurInfo->rcClip.left) CurInfo->rcClip.right = CurInfo->rcClip.left; CurInfo->rcClip.top = max(prcl->top, DesktopWindow->rcWindow.top); CurInfo->rcClip.bottom = min(prcl->bottom, DesktopWindow->rcWindow.bottom); if (CurInfo->rcClip.bottom < CurInfo->rcClip.top) CurInfo->rcClip.bottom = CurInfo->rcClip.top; /* Make sure cursor is in clipping region */ UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, 0, 0, FALSE); } else { CurInfo->bClipped = FALSE; } return TRUE; }
DWORD APIENTRY NtUserSetScrollInfo( HWND hWnd, int fnBar, LPCSCROLLINFO lpsi, BOOL bRedraw) { PWND Window = NULL; NTSTATUS Status; SCROLLINFO ScrollInfo; DECLARE_RETURN(DWORD); USER_REFERENCE_ENTRY Ref; TRACE("Enter NtUserSetScrollInfo\n"); UserEnterExclusive(); if(!(Window = UserGetWindowObject(hWnd)) || // FIXME: Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN( 0); } UserRefObjectCo(Window, &Ref); Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( 0); } RETURN(co_IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw)); CLEANUP: if (Window) UserDerefObjectCo(Window); TRACE("Leave NtUserSetScrollInfo, ret=%lu\n", _ret_); UserLeave(); END_CLEANUP; }
BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook) { PWND DesktopWindow; PSYSTEM_CURSORINFO CurInfo; MSG Msg; RECTL rcClip; POINT pt; if(!(DesktopWindow = UserGetDesktopWindow())) { return FALSE; } CurInfo = IntGetSysCursorInfo(); /* Clip cursor position */ if (!CurInfo->bClipped) rcClip = DesktopWindow->rcClient; else rcClip = CurInfo->rcClip; if(x >= rcClip.right) x = rcClip.right - 1; if(x < rcClip.left) x = rcClip.left; if(y >= rcClip.bottom) y = rcClip.bottom - 1; if(y < rcClip.top) y = rcClip.top; pt.x = x; pt.y = y; /* 1. Generate a mouse move message, this sets the htEx and Track Window too. */ Msg.message = WM_MOUSEMOVE; Msg.wParam = UserGetMouseButtonsState(); Msg.lParam = MAKELPARAM(x, y); Msg.pt = pt; co_MsqInsertMouseMessage(&Msg, flags, dwExtraInfo, Hook); /* 2. Store the new cursor position */ gpsi->ptCursor = pt; return TRUE; }
BOOL FASTCALL co_IntMouseActivateWindow(PWND Wnd) { HWND Top; PWND TopWindow; USER_REFERENCE_ENTRY Ref; ASSERT_REFS_CO(Wnd); if (Wnd->style & WS_DISABLED) { BOOL Ret; PWND TopWnd; PWND DesktopWindow = UserGetDesktopWindow(); if (DesktopWindow) { Top = IntFindChildWindowToOwner(DesktopWindow, Wnd); if ((TopWnd = ValidateHwndNoErr(Top))) { UserRefObjectCo(TopWnd, &Ref); Ret = co_IntMouseActivateWindow(TopWnd); UserDerefObjectCo(TopWnd); return Ret; } } return FALSE; } TopWindow = UserGetAncestor(Wnd, GA_ROOT); //if (TopWindow) {ERR("MAW 2 pWnd %p hWnd %p\n",TopWindow,TopWindow->head.h);} if (!TopWindow) return FALSE; /* TMN: Check return value from this function? */ UserRefObjectCo(TopWindow, &Ref); co_IntSetForegroundAndFocusWindow(TopWindow, TRUE); UserDerefObjectCo(TopWindow); return TRUE; }
BOOL FASTCALL co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOOL Async) { USER_REFERENCE_ENTRY Ref, RefPrev; HANDLE OldTID, NewTID; PTHREADINFO pti, ptiOld, ptiNew; BOOL InAAPM = FALSE; if (Window) { pti = PsGetCurrentThreadWin32Thread(); UserRefObjectCo(Window, &Ref); if (WindowPrev) UserRefObjectCo(WindowPrev, &RefPrev); /* Send palette messages */ if (gpsi->PUSIFlags & PUSIF_PALETTEDISPLAY && //co_IntPostOrSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0)) co_IntSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0)) { UserSendNotifyMessage( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)UserHMGetHandle(Window), 0); } //// Fixes bug 7089. if (!(Window->style & WS_CHILD)) { PWND pwndTemp = co_GetDesktopWindow(Window)->spwndChild; while (pwndTemp && !(pwndTemp->style & WS_VISIBLE)) pwndTemp = pwndTemp->spwndNext; if (Window != pwndTemp || (WindowPrev && !IntIsWindowVisible(WindowPrev))) { if (!Async || pti->MessageQueue == gpqForeground) { UINT flags = SWP_NOSIZE | SWP_NOMOVE; if (Window == pwndTemp) flags |= SWP_NOACTIVATE; //ERR("co_IntSendActivateMessages SetWindowPos! Async %d pti Q == FGQ %d\n",Async,pti->MessageQueue == gpqForeground); co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, flags); } } } //// //// CORE-1161 and CORE-6651 if (Window->spwndPrev) { HWND *phwndTopLevel, *phwndCurrent; PWND pwndCurrent, pwndDesktop; pwndDesktop = UserGetDesktopWindow(); if (Window->spwndParent == pwndDesktop ) { phwndTopLevel = IntWinListChildren(pwndDesktop); phwndCurrent = phwndTopLevel; while(*phwndCurrent) { pwndCurrent = UserGetWindowObject(*phwndCurrent); if (pwndCurrent && pwndCurrent->spwndOwner == Window ) { co_WinPosSetWindowPos(pwndCurrent, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); } phwndCurrent++; } ExFreePool(phwndTopLevel); } } //// OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL; NewTID = IntGetWndThreadId(Window); ptiOld = WindowPrev ? WindowPrev->head.pti : NULL; ptiNew = Window->head.pti; //ERR("SendActivateMessage Old -> %x, New -> %x\n", OldTID, NewTID); if (!(pti->TIF_flags & TIF_INACTIVATEAPPMSG) && (!WindowPrev || OldTID != NewTID) ) { PWND cWindow; HWND *List, *phWnd; List = IntWinListChildren(UserGetDesktopWindow()); if ( List ) { if ( OldTID ) { ptiOld->TIF_flags |= TIF_INACTIVATEAPPMSG; // Note: Do not set pci flags, this does crash! for (phWnd = List; *phWnd; ++phWnd) { cWindow = ValidateHwndNoErr(*phWnd); if (cWindow && cWindow->head.pti == ptiOld) { // FALSE if the window is being deactivated, // ThreadId that owns the window being activated. co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID); } } ptiOld->TIF_flags &= ~TIF_INACTIVATEAPPMSG; } if ( NewTID ) { //// Prevents a resource crash due to reentrance! InAAPM = TRUE; pti->TIF_flags |= TIF_INACTIVATEAPPMSG; //// for (phWnd = List; *phWnd; ++phWnd) { cWindow = ValidateHwndNoErr(*phWnd); if (cWindow && cWindow->head.pti == ptiNew) { // TRUE if the window is being activated, // ThreadId that owns the window being deactivated. co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID); } } } ExFreePoolWithTag(List, USERTAG_WINDOWLIST); } } if (WindowPrev) UserDerefObjectCo(WindowPrev); // Now allow the previous window to die. if (Window->state & WNDS_ACTIVEFRAME) { // If already active frame do not allow NCPaint. //ERR("SendActivateMessage Is Active Frame!\n"); Window->state |= WNDS_NONCPAINT; } if (Window->style & WS_MINIMIZE) { TRACE("Widow was minimized\n"); } co_IntMakeWindowActive(Window); /* FIXME: IntIsWindow */ co_IntSendMessageNoWait( UserHMGetHandle(Window), WM_NCACTIVATE, (WPARAM)(Window == (gpqForeground ? gpqForeground->spwndActive : NULL)), 0); //(LPARAM)hWndPrev); co_IntSendMessageNoWait( UserHMGetHandle(Window), WM_ACTIVATE, MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE, Window->style & WS_MINIMIZE), (LPARAM)(WindowPrev ? UserHMGetHandle(WindowPrev) : 0)); if (!Window->spwndOwner && !IntGetParent(Window)) { // FIXME lParam; The value is TRUE if the window is in full-screen mode, or FALSE otherwise. co_IntShellHookNotify(HSHELL_WINDOWACTIVATED, (WPARAM) UserHMGetHandle(Window), FALSE); } Window->state &= ~WNDS_NONCPAINT; UserDerefObjectCo(Window); } return InAAPM; }
BOOL FASTCALL co_IntSetActiveWindow(PWND Wnd OPTIONAL, BOOL bMouse, BOOL bFocus, BOOL Async) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; PWND pWndChg, WndPrev; // State changes. HWND hWndPrev; HWND hWnd = 0; BOOL InAAPM; CBTACTIVATESTRUCT cbt; //ERR("co_IntSetActiveWindow 1\n"); if (Wnd) { ASSERT_REFS_CO(Wnd); hWnd = UserHMGetHandle(Wnd); if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; if (Wnd == UserGetDesktopWindow()) return FALSE; //ERR("co_IntSetActiveWindow 1a hWnd 0x%p\n",hWnd); } //ERR("co_IntSetActiveWindow 2\n"); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL; pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch. while (Wnd) { BOOL Ret, DoFG, AllowFG; if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE; if (ThreadQueue == Wnd->head.pti->MessageQueue) { if (IsAllowedFGActive(pti, Wnd)) { DoFG = TRUE; } else { //ERR("co_IntSetActiveWindow 3 Go Out!\n"); break; } AllowFG = !pti->cVisWindows; // Nothing is visable. //ERR("co_IntSetActiveWindow 3a DoFG = %d AllowFG = %d\n",DoFG,AllowFG); } else //if (ThreadQueue != Wnd->head.pti->MessageQueue) { //PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... //if (!ForegroundQueue || ForegroundQueue == ThreadQueue) if (!gpqForeground || gpqForeground == ThreadQueue) { DoFG = TRUE; } else DoFG = FALSE; if (DoFG) { if (pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE || pti->cVisWindows) AllowFG = TRUE; else AllowFG = FALSE; } else AllowFG = FALSE; //ERR("co_IntSetActiveWindow 3b DoFG = %d AllowFG = %d\n",DoFG,AllowFG); } Ret = FALSE; if (DoFG) { pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; //ERR("co_IntSetActiveWindow 3c FG set\n"); Ret = co_IntSetForegroundAndFocusWindow(Wnd, bMouse); if (AllowFG) { pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; } else { pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; } } return Ret; } /* Call CBT hook chain */ cbt.fMouse = bMouse; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) { ERR("SetActiveWindow: WH_CBT Call Hook return!\n"); return FALSE; } if ( ThreadQueue->spwndActive && ThreadQueue->spwndActive->state & WNDS_DESTROYED ) ThreadQueue->spwndActive = NULL; else ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; WndPrev = ThreadQueue->spwndActive; // Keep to save changing active. if (WndPrev) { if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue; if (!co_IntSendDeactivateMessages(UserHMGetHandle(WndPrev), hWnd)) return FALSE; } WndPrev = ThreadQueue->spwndActive; // Again keep to save changing active. // While in calling message proc or hook: // Fail if a preemptive switch was made, current active not made previous, // focus window is dead or no longer the same thread queue. if ( ThreadQueue->spwndActivePrev != ThreadQueue->spwndActive || pWndChg != WndPrev || (Wnd && !VerifyWnd(Wnd)) || ThreadQueue != pti->MessageQueue ) { ERR("SetActiveWindow: Summery ERROR, active state changed!\n"); return FALSE; } if (!WndPrev) ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); //// Breaks Atl-Esc/Tab via User32. ////FindRemoveAsyncMsg(Wnd,(WPARAM)Wnd); // Clear out activate ASYNC messages. /* check if the specified window can be set in the input data of a given queue */ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) { /* set the current thread active window */ ThreadQueue->spwndActive = Wnd; } WndPrev = VerifyWnd(ThreadQueue->spwndActivePrev); // Now should be set but verify it again. InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async); /* now change focus if necessary */ if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE)) { /* Do not change focus if the window is no longer active */ if (ThreadQueue->spwndActive == Wnd) { if (!ThreadQueue->spwndFocus || !Wnd || UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd) { co_UserSetFocus(Wnd); } } } if (InAAPM) { pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; } // FIXME: Used in the menu loop!!! //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE; //ERR("co_IntSetActiveWindow Exit\n"); if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; return (ThreadQueue->spwndActive == Wnd); }
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; }
HWND FASTCALL co_UserSetFocus(PWND Window) { HWND hWndPrev = 0; PWND pwndTop; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; if (Window) ASSERT_REFS_CO(Window); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); TRACE("Enter SetFocus hWnd 0x%p pti 0x%p\n",Window ? UserHMGetHandle(Window) : 0, pti ); hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; if (Window != 0) { if (hWndPrev == UserHMGetHandle(Window)) { return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; /* Nothing to do */ } if (Window->head.pti->MessageQueue != ThreadQueue) { ERR("SetFocus Must have the same Q!\n"); return 0; } /* Check if we can set the focus to this window */ pwndTop = Window; for (;;) { if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0; if (!pwndTop->spwndParent || pwndTop->spwndParent == UserGetDesktopWindow()) { if ((pwndTop->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return 0; break; } if (pwndTop->spwndParent == UserGetMessageWindow()) return 0; pwndTop = pwndTop->spwndParent; } if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) { ERR("SetFocus 1 WH_CBT Call Hook return!\n"); return 0; } /* Activate pwndTop if needed. */ if (pwndTop != ThreadQueue->spwndActive) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop. if (ThreadQueue != ForegroundQueue) // HACK see rule 2 & 3. { if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE)) { ERR("SetFocus: Set Foreground and Focus Failed!\n"); return 0; } } /* Set Active when it is needed. */ if (pwndTop != ThreadQueue->spwndActive) { if (!co_IntSetActiveWindow(pwndTop, NULL, FALSE, FALSE, FALSE)) { ERR("SetFocus: Set Active Failed!\n"); return 0; } } /* Abort if window destroyed */ if (Window->state2 & WNDS2_INDESTROY) return 0; /* Do not change focus if the window is no longer active */ if (pwndTop != ThreadQueue->spwndActive) { ERR("SetFocus: Top window did not go active!\n"); return 0; } } // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE. hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; IntSendFocusMessages( pti, Window); TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h); } else /* NULL hwnd passed in */ { // if (!hWndPrev) return 0; /* nothing to do */ if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { ERR("SetFocus: 2 WH_CBT Call Hook return!\n"); return 0; } /* set the current thread focus window null */ IntSendFocusMessages( pti, NULL); } return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; }
BOOL FASTCALL co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, BOOL Async) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; PWND pWndChg, WndPrev; // State changes. HWND hWndPrev; HWND hWnd = 0; BOOL InAAPM; CBTACTIVATESTRUCT cbt; if (Wnd) { ASSERT_REFS_CO(Wnd); hWnd = UserHMGetHandle(Wnd); if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; if (Wnd == UserGetDesktopWindow()) return FALSE; } pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL; if (Prev) *Prev = hWndPrev; if (hWndPrev == hWnd) return TRUE; pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch. if (Wnd) { if (ThreadQueue != Wnd->head.pti->MessageQueue) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... if (!ForegroundQueue || ForegroundQueue == ThreadQueue) { return co_IntSetForegroundAndFocusWindow(Wnd, bMouse); } } if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE; } /* Call CBT hook chain */ cbt.fMouse = bMouse; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) { ERR("SetActiveWindow: WH_CBT Call Hook return!\n"); return FALSE; } if ( ThreadQueue->spwndActive && ThreadQueue->spwndActive->state & WNDS_DESTROYED ) ThreadQueue->spwndActive = NULL; else ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; WndPrev = ThreadQueue->spwndActive; // Keep to save changing active. if (WndPrev) { if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue; if (!co_IntSendDeactivateMessages(hWndPrev, hWnd)) return FALSE; } // While in calling message proc or hook: // Fail if a preemptive switch was made, current active not made previous, // focus window is dead or no longer the same thread queue. if ( ThreadQueue->spwndActivePrev != ThreadQueue->spwndActive || pWndChg != ThreadQueue->spwndActive || (Wnd && !VerifyWnd(Wnd)) || ThreadQueue != pti->MessageQueue ) { ERR("SetActiveWindow: Summery ERROR, active state changed!\n"); return FALSE; } if (!WndPrev) ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); /* check if the specified window can be set in the input data of a given queue */ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) { /* set the current thread active window */ ThreadQueue->spwndActive = Wnd; } InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async); /* now change focus if necessary */ if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE)) { /* Do not change focus if the window is no longer active */ if (ThreadQueue->spwndActive == Wnd) { if (!ThreadQueue->spwndFocus || !Wnd || UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd) { co_UserSetFocus(Wnd); } } } if (InAAPM) { pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; pti->pClientInfo->dwTIFlags = pti->TIF_flags; } // FIXME: Used in the menu loop!!! //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE; if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; return (ThreadQueue->spwndActive == Wnd); }
BOOL APIENTRY NtUserEnableScrollBar( HWND hWnd, UINT wSBflags, UINT wArrows) { UINT OrigArrows; PWND Window = NULL; PSCROLLBARINFO InfoV = NULL, InfoH = NULL; BOOL Chg = FALSE; DECLARE_RETURN(BOOL); USER_REFERENCE_ENTRY Ref; TRACE("Enter NtUserEnableScrollBar\n"); UserEnterExclusive(); if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN(FALSE); } UserRefObjectCo(Window, &Ref); if (!co_IntCreateScrollBars(Window)) { RETURN( FALSE); } OrigArrows = Window->pSBInfo->WSBflags; Window->pSBInfo->WSBflags = wArrows; if (wSBflags == SB_CTL) { if ((wArrows == ESB_DISABLE_BOTH || wArrows == ESB_ENABLE_BOTH)) IntEnableWindow(hWnd, (wArrows == ESB_ENABLE_BOTH)); RETURN(TRUE); } if(wSBflags != SB_BOTH && !SBID_IS_VALID(wSBflags)) { EngSetLastError(ERROR_INVALID_PARAMETER); ERR("Trying to set scrollinfo for unknown scrollbar type %u", wSBflags); RETURN(FALSE); } switch(wSBflags) { case SB_BOTH: InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT); /* Fall through */ case SB_HORZ: InfoH = IntGetScrollbarInfoFromWindow(Window, SB_HORZ); break; case SB_VERT: InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT); break; default: RETURN(FALSE); } if(InfoV) Chg = IntEnableScrollBar(FALSE, InfoV, wArrows); if(InfoH) Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg); ERR("FIXME: EnableScrollBar wSBflags %u wArrows %u Chg %d\n", wSBflags, wArrows, Chg); // Done in user32: // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); RETURN( Chg); if (OrigArrows == wArrows) RETURN( FALSE); RETURN( TRUE); CLEANUP: if (Window) UserDerefObjectCo(Window); TRACE("Leave NtUserEnableScrollBar, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }