BOOL FASTCALL co_IntMakeWindowActive(PWND Window) { PWND spwndOwner; if (VerifyWnd(Window)) { // Set last active for window and it's owner. spwndOwner = Window; while (spwndOwner->spwndOwner) { spwndOwner = spwndOwner->spwndOwner; } spwndOwner->spwndLastActive = Window; return TRUE; } ERR("MakeWindowActive Failed!\n"); return FALSE; }
PREGION FASTCALL VIS_ComputeVisibleRegion( PWND Wnd, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings) { PREGION VisRgn, ClipRgn; PWND PreviousWindow, CurrentWindow, CurrentSibling; if (!Wnd || !(Wnd->style & WS_VISIBLE)) { return NULL; } VisRgn = NULL; if (ClientArea) { VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcClient); } else { VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow); } /* * Walk through all parent windows and for each clip the visble region * to the parent's client area and exclude all siblings that are over * our window. */ PreviousWindow = Wnd; CurrentWindow = Wnd->spwndParent; while (CurrentWindow) { if (!VerifyWnd(CurrentWindow)) { ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow); if (VisRgn) REGION_Delete(VisRgn); return NULL; } if (!(CurrentWindow->style & WS_VISIBLE)) { if (VisRgn) REGION_Delete(VisRgn); return NULL; } ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcClient); IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); REGION_Delete(ClipRgn); if ((PreviousWindow->style & WS_CLIPSIBLINGS) || (PreviousWindow == Wnd && ClipSiblings)) { CurrentSibling = CurrentWindow->spwndChild; while ( CurrentSibling != NULL && CurrentSibling != PreviousWindow ) { if ((CurrentSibling->style & WS_VISIBLE) && !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT)) { ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentSibling->rcWindow); /* Combine it with the window region if available */ if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE)) { PREGION SiblingClipRgn = REGION_LockRgn(CurrentSibling->hrgnClip); if (SiblingClipRgn) { REGION_bOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top); IntGdiCombineRgn(ClipRgn, ClipRgn, SiblingClipRgn, RGN_AND); REGION_bOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top); REGION_UnlockRgn(SiblingClipRgn); } } IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); REGION_Delete(ClipRgn); } CurrentSibling = CurrentSibling->spwndNext; } } PreviousWindow = CurrentWindow; CurrentWindow = CurrentWindow->spwndParent; } if (ClipChildren) { CurrentWindow = Wnd->spwndChild; while (CurrentWindow) { if ((CurrentWindow->style & WS_VISIBLE) && !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT)) { ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcWindow); /* Combine it with the window region if available */ if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE)) { PREGION CurrentRgnClip = REGION_LockRgn(CurrentWindow->hrgnClip); if (CurrentRgnClip) { REGION_bOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top); IntGdiCombineRgn(ClipRgn, ClipRgn, CurrentRgnClip, RGN_AND); REGION_bOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top); REGION_UnlockRgn(CurrentRgnClip); } } IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); REGION_Delete(ClipRgn); } CurrentWindow = CurrentWindow->spwndNext; } } if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE)) { PREGION WndRgnClip = REGION_LockRgn(Wnd->hrgnClip); if (WndRgnClip) { REGION_bOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top); IntGdiCombineRgn(VisRgn, VisRgn, WndRgnClip, RGN_AND); REGION_bOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top); REGION_UnlockRgn(WndRgnClip); } } return VisRgn; }
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); }
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); }