BOOL _ShowWindowAsync( PWND pwnd, int cmdShow) { return PostEventMessage(GETPTI(pwnd), GETPTI(pwnd)->pq, QEVENT_SHOWWINDOW, NULL, 0,(DWORD)HWq(pwnd), MAKELONG(cmdShow, gfAnimate)); }
void xxxTrackMouseMove(PWND pwnd, int htEx, UINT message) { BOOL fNewpwndTrack; DWORD dwDTCancel = 0; TL tlpwnd; LPWSTR pstr; PDESKTOP pdesk = PtiCurrent()->rpdesk; PTHREADINFO ptiTrack; #if DBG /* * Let's warn if this function gets reenterd so we can make sure * nothing bad will follow. This should be a rare situation. * Look in gptiReEntered to find out who is already here. */ static UINT gcReEntered = 0; static PTHREADINFO gptiReEntered; if(gcReEntered++ != 0){ RIPMSG2(RIP_WARNING, "Reentered xxxTrackMouseMove; previous thread was %#p, current thread is %#p", gptiReEntered, PtiCurrent()); } gptiReEntered = PtiCurrent(); CheckLock(pwnd); /* * We must be on an interactive window station. */ if (pdesk->rpwinstaParent != NULL && pdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO) { RIPMSG0(RIP_ERROR, "Can't use tooltips on non-interactive winsta"); } { static POINT pt = {0, 0}; #ifdef UNDONE /* * We might have taken a guess on the hit test (see FindNCHitEx) * so if we're at the same point and same window, something * might be fishy */ if ((pt.x == gpsi->ptCursor.x) && (pt.y == gpsi->ptCursor.y) && (pdesk->spwndTrack == pwnd)) { RIPMSG1(RIP_WARNING, "xxxTrackMouseMove: Same point & window. %#p", pwnd); } #endif /* * Something is supposed to have changed or we're wasting time */ UserAssert((pt.x != gpsi->ptCursor.x) || (pt.y != gpsi->ptCursor.y) || (pdesk->spwndTrack != pwnd) || (pdesk->htEx != htEx) || (message != WM_MOUSEMOVE)); /* * Remember last tracked point */ pt = gpsi->ptCursor; } /* * pwnd is supposed to be on the current thread and queue */ UserAssert(PtiCurrent() == GETPTI(pwnd)); UserAssert(PtiCurrent()->pq == GETPTI(pwnd)->pq); #endif /* * Have we switched windows? */ fNewpwndTrack = (pdesk->spwndTrack != pwnd); /* * If no tracking is taking place, just go set the new * tracking state */ if (!(pdesk->dwDTFlags & DF_MOUSEMOVETRK)) { goto SetNewState; } /* * Potentially while we leave the critical section below in * xxxCancelMouseMoveTracking, spwndTrack could be destroyed and unlocked * and then we go and create the tooltip. This would mean that * DF_TOOLTIPACTIVE (part of DF_MOUSEMOVETRK test above) would be set, * but pdesk->spwndTrack would be NULL and we can AV dereferencing * pdesk->spwndTrack below. Prevent this by making the check here. */ if (pdesk->spwndTrack == NULL) { goto SetNewState; } /* * Nuke hottracking and deactivate tooltip state, if any. * Do it sychronously if we're tracking on the current queue; * Otherwise, post an event and let it happen later. */ ptiTrack = GETPTI(pdesk->spwndTrack); if (PtiCurrent()->pq == ptiTrack->pq) { dwDTCancel |= DF_HOTTRACKING; } else if (pdesk->dwDTFlags & (DF_HOTTRACKING | DF_TOOLTIPACTIVE)) { PostEventMessage(ptiTrack, ptiTrack->pq, QEVENT_CANCELMOUSEMOVETRK, pdesk->spwndTrack, pdesk->dwDTFlags, pdesk->htEx, DF_HOTTRACKING); /* * Paranoid assertion. If we're switching queues, we must * be switching windows. Did we just go through * ReattachThreads? */ UserAssert(pwnd != pdesk->spwndTrack); pdesk->dwDTFlags &= ~(DF_HOTTRACKING | DF_TOOLTIPACTIVE); } /* * If we're on the client area or the user clicked, * nuke the tooltip (if any). * Since we might want to re-show the tooltip, we don't nuke it * now if we swichted windows (we'll nuke it later if needed) */ if ((htEx == HTCLIENT) || (message != WM_MOUSEMOVE)) { dwDTCancel |= DF_TOOLTIPACTIVE; } /* * If we switched windows or crossed client/nonclinet boundaries, * end track mouse leave/hover. */ if (fNewpwndTrack || ((pdesk->htEx == HTCLIENT) ^ (htEx == HTCLIENT))) { dwDTCancel |= DF_TRACKMOUSEEVENT; } /* * Cancel whatever is active and needs to go away */ ThreadLockAlways(pdesk->spwndTrack, &tlpwnd); xxxCancelMouseMoveTracking(pdesk->dwDTFlags, pdesk->spwndTrack, pdesk->htEx, dwDTCancel); ThreadUnlock(&tlpwnd); pdesk->dwDTFlags &= ~dwDTCancel; SetNewState: /* * Hottracking/tooltip on mouse move if on NC hitest and enabled */ if ((htEx != HTCLIENT) && (message == WM_MOUSEMOVE) && TestEffectUP(HOTTRACKING)) { /* * Hottrack the new hit test area */ if (xxxHotTrack(pwnd, htEx, TRUE)) { pdesk->dwDTFlags |= DF_HOTTRACKING; } /* * Remove/set the tool tip. * We always do this synchronously because it doesn't mess * with pwnd's or spwnTrack's queue */ if ((pstr = IsTooltipHittest(pwnd, LOWORD(htEx))) != NULL) { PTOOLTIPWND pttwnd = (PTOOLTIPWND)pdesk->spwndTooltip; ThreadLockAlways(pttwnd, &tlpwnd); xxxCreateTooltip(pttwnd, pstr); ThreadUnlock(&tlpwnd); pdesk->dwDTFlags |= DF_TOOLTIP; } else { PTOOLTIPWND pttwnd = (PTOOLTIPWND)pdesk->spwndTooltip; ThreadLockAlways(pttwnd, &tlpwnd); xxxResetTooltip(pttwnd); ThreadUnlock(&tlpwnd); } } /* if (htEx != HTCLIENT) */ ValidateThreadLocks(NULL, PtiCurrent()->ptl, (ULONG_PTR)&pwnd, TRUE); /* * Update new track window if needed. */ if (fNewpwndTrack) { PWND pwndActivate; Lock(&pdesk->spwndTrack, pwnd); /* * Active window tracking. * If there is non-zero timeout, get the window we're supposed to activate * and set the timer. Otherwise, set the queue flag so * xxxActiveWindowTracking can do its thing. */ if ((message == WM_MOUSEMOVE) && TestUP(ACTIVEWINDOWTRACKING)) { if (UP(ACTIVEWNDTRKTIMEOUT) != 0) { pwndActivate = GetActiveTrackPwnd(pwnd, NULL); if (pwndActivate != NULL) { InternalSetTimer(pwndActivate, IDSYS_WNDTRACKING, UP(ACTIVEWNDTRKTIMEOUT), xxxSystemTimerProc, TMRF_SYSTEM); } } else { PtiCurrent()->pq->QF_flags |= QF_ACTIVEWNDTRACKING; } /* if (TestUP(ACTIVEWNDTRKZORDER)) */ } /* if (TestUP(ACTIVEWINDOWTRACKING)) */ } /* * Save new hit test code */ pdesk->htEx = htEx; #if DBG --gcReEntered; #endif }