Example #1
0
PWND xxxSetCapture(
    PWND pwnd)
{
    PQ   pq;
    PWND pwndCaptureOld;
    HWND hwndCaptureOld;

    pq = (PQ)PtiCurrent()->pq;

    /*
     * Don't allow the app to set capture to a window
     * from another queue.
     */
    if ((pwnd != NULL) && GETPTI(pwnd)->pq != pq)
        return NULL;

    /*
     * If full screen capture don't allow any other capture
     */
    if (gspwndScreenCapture)
        return NULL;

    pwndCaptureOld = pq->spwndCapture;
    hwndCaptureOld = HW(pwndCaptureOld);

    xxxCapture(PtiCurrent(), pwnd, CLIENT_CAPTURE);

    if (hwndCaptureOld != NULL) {

        if (RevalidateHwnd(hwndCaptureOld))
            return pwndCaptureOld;
    }

    return NULL;
}
Example #2
0
HANDLE xxxLoadHmodIndex(
    int iatom,
    BOOL bWx86KnownDll)
{
    WCHAR pszLibName[MAX_PATH];
    HANDLE hmod;
    UNICODE_STRING strLibrary;
    PTHREADINFO    ptiCurrent = PtiCurrent();

    UserAssert((!gptiRit || gptiRit->ppi != PtiCurrent()->ppi) &&
                "Shouldn't load global hooks on system process - gptiRit->ppi is the system process");

    if (iatom >= catomSysTableEntries) {
        RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Index out of range");
        return NULL;
    }

    UserGetAtomName(aatomSysLoaded[iatom], pszLibName, sizeof(pszLibName)/sizeof(WCHAR));

    /*
     * Call back the client to load the library.
     */
    RtlInitUnicodeString(&strLibrary, pszLibName);
    hmod = ClientLoadLibrary(&strLibrary, bWx86KnownDll);

    if (hmod != NULL) {
        /*
         * Check to make sure another thread hasn't loaded this library
         * while we were outside the critical section.
         */
        if (!TESTHMODLOADED(ptiCurrent, iatom)) {
            /*
             * Go ahead and bump the reference count.
             */
            acatomSysUse[iatom]++;
            SETHMODLOADED(ptiCurrent, iatom, hmod);

        } else {
            /*
             * Another thread loaded it while we were outside the
             * critical section.  Unload it so the system's
             * reference count is correct.
             */
            ClientFreeLibrary(ptiCurrent->ppi->ahmodLibLoaded[iatom]);
        }
    }

    return hmod;
}
Example #3
0
void xxxShowTooltip(PTOOLTIPWND pttwnd)
{
    SIZE size;
    POINT pt;
    DWORD dwFlags;

    CheckLock(pttwnd);

    if (pttwnd->pstr == NULL)
        return;

    if (pttwnd->pstr == gszCAPTIONTOOLTIP) {

        PWND pwnd = PtiCurrent()->rpdesk->spwndTrack;
        /*
         * The window text might have changed in callbacks, retrieve it now
         */
        if (TestWF(pwnd, WEFTRUNCATEDCAPTION) && pwnd->strName.Length) {
            wcsncpycch(gszCAPTIONTOOLTIP, pwnd->strName.Buffer, CAPTIONTOOLTIPLEN-1);
            gszCAPTIONTOOLTIP[CAPTIONTOOLTIPLEN-1] = 0;
        } else {
            return;
        }
    }

    TooltipGetSize(pttwnd, &size);
    TooltipGetPosition(pttwnd, &size, &pt);

    dwFlags = SWP_CREATESPB | SWP_SHOWWINDOW | SWP_NOACTIVATE;
    if (TestEffectUP(TOOLTIPANIMATION)) {
        dwFlags |= SWP_NOREDRAW;
    }
    xxxSetWindowPos((PWND)pttwnd, PWND_TOP, pt.x, pt.y, size.cx, size.cy,
            dwFlags);
}
Example #4
0
/***************************************************************************\
* xxxHotTrackMenu
*
* Hot-track a menu item in the menu bar.
\***************************************************************************/
BOOL xxxHotTrackMenu(PWND pwnd, UINT nItem, BOOL fDraw)
{
    PMENU pmenu = pwnd->spmenu;
    PITEM pItem;
    HDC   hdc;
    UINT  oldAlign;
    TL tlpmenu;

    CheckLock(pwnd);

    /*
     * The window may have lied about the hit-test code on
     * WM_NCHITTEST. Make sure it does indeed have a menu.
     */
    if (!TestWF(pwnd, WFMPRESENT) || pmenu == NULL)
        return FALSE;

    if (nItem >= pmenu->cItems) {
        RIPMSG0(RIP_WARNING, "xxxHotTrackMenu: menu too large");
        return FALSE;
    }

    pItem = &pmenu->rgItems[nItem];

    /*
     * Make sure we draw on the right spot
     */
    ThreadLock(pmenu, &tlpmenu);
    xxxMNRecomputeBarIfNeeded(pwnd, pmenu);
    ValidateThreadLocks(NULL, PtiCurrent()->ptl, (ULONG_PTR)&tlpmenu, TRUE);

    if (fDraw) {
        if (TestMFS(pItem, MF_GRAYED)) {
            ThreadUnlock(&tlpmenu);
            return FALSE;
        }
        SetMFS(pItem, MFS_HOTTRACK);
    } else {
        ClearMFS(pItem, MFS_HOTTRACK);
    }

    hdc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_USESTYLE | DCX_CACHE);
    GreSelectBrush(hdc, SYSHBR(MENUTEXT));
    GreSelectFont(hdc, ghMenuFont);

    oldAlign = GreGetTextAlign(hdc);
    if (pmenu->rgItems && TestMFT(pmenu->rgItems, MFT_RIGHTORDER))
        GreSetTextAlign(hdc, oldAlign | TA_RTLREADING);

    /*
     * When the item is not owner draw, xxxDrawMenuItem does not
     * call back and does not leave the critical section.
     */
    xxxDrawMenuItem(hdc, pmenu, pItem, 0);
    GreSetTextAlign(hdc, oldAlign);
    ThreadUnlock(&tlpmenu);

    _ReleaseDC(hdc);
    return TRUE;
}
Example #5
0
VOID ZapActiveAndFocus(VOID)
{
   PQ pq = PtiCurrent()->pq;

   Unlock(&pq->spwndActive);
   Unlock(&pq->spwndFocus);
}
Example #6
0
BOOL xxxReleaseCapture(VOID)
{
    PTHREADINFO ptiCurrent = PtiCurrent();

    /*
     * If we're releasing the capture from a window during tracking,
     * cancel tracking first.
     */
    if (ptiCurrent->pmsd != NULL) {

        /*
         * Only remove the tracking rectangle if it's
         * been made visible.
         */
        if (ptiCurrent->TIF_flags & TIF_TRACKRECTVISIBLE) {

            bSetDevDragRect(gpDispInfo->hDev, NULL, NULL);

            if (!(ptiCurrent->pmsd->fDragFullWindows))
                xxxDrawDragRect(ptiCurrent->pmsd, NULL, DDR_ENDCANCEL);

            ptiCurrent->TIF_flags &= ~(TIF_TRACKRECTVISIBLE | TIF_MOVESIZETRACKING);
        }
    }

    xxxCapture(ptiCurrent, NULL, NO_CAP_CLIENT);

    return TRUE;
}
Example #7
0
VOID xxxDoSyncPaint(
    PWND  pwnd,
    DWORD flags)
{
    CheckLock(pwnd);

    /*
     * If any of our non-clipchildren parents have an update region, don't
     * do anything.  This way we won't redraw our background or frame out
     * of order, only to have it get obliterated when our parent erases his
     * background.
     */
    if (ParentNeedsPaint(pwnd))
        return;

    /*
     * First of all if we are going to be queueing any WM_SYNCPAINT messages
     * to windows of another thread do it first while the window's update
     * regions are still in sync.  This way there is no chance the update
     * region will be incorrect (through window movement during callbacks of
     * the WM_ERASEBKGND|WM_NCPAINT messages).
     */
    DoQueuedSyncPaint(pwnd, flags, PtiCurrent());
    xxxInternalDoSyncPaint(pwnd, flags);
}
Example #8
0
VOID xxxSendNCPaint(
    PWND pwnd,
    HRGN hrgnUpdate)
{
    CheckLock(pwnd);

    /*
     * Clear the WFSENDNCPAINT bit...
     */
    ClrWF(pwnd, WFSENDNCPAINT);

    /*
     * If the window is active, but its FRAMEON bit hasn't
     * been set yet, set it and make sure that the entire frame
     * gets redrawn when we send the NCPAINT.
     */
    if ((pwnd == PtiCurrent()->pq->spwndActive) && !TestWF(pwnd, WFFRAMEON)) {
        SetWF(pwnd, WFFRAMEON);
        hrgnUpdate = HRGN_FULL;
        ClrWF(pwnd, WFNONCPAINT);
    }

    /*
     * If PixieHack() has set the WM_NCPAINT bit, we must be sure
     * to send with hrgnClip == HRGN_FULL.  (see PixieHack() in wmupdate.c)
     */
    if (TestWF(pwnd, WFPIXIEHACK)) {
        ClrWF(pwnd, WFPIXIEHACK);
        hrgnUpdate = HRGN_FULL;
    }

    if (hrgnUpdate)
        xxxSendMessage(pwnd, WM_NCPAINT, (WPARAM)hrgnUpdate, 0L);
}
Example #9
0
VOID DestroyThreadsHotKeys()
{
    PHOTKEY *pphk;
    PHOTKEY phk;
    PTHREADINFO ptiCurrent = PtiCurrent();

    pphk = &gphkFirst;
    while (*pphk) {
        if ((*pphk)->pti == ptiCurrent) {
            phk = *pphk;
            *pphk = (*pphk)->phkNext;

            /*
             * Unlock the object stored here.
             */
            if ((phk->spwnd != PWND_FOCUS) && (phk->spwnd != PWND_INPUTOWNER)) {
                Unlock(&phk->spwnd);
            }

            UserFreePool(phk);
        } else {
            pphk = &((*pphk)->phkNext);
        }
    }
}
Example #10
0
/***************************************************************************\
* UpdatePerUserKeyboardIndicators
*
* Sets the initial keyboard indicators according to the user's profile.
*
* ASSUMPTIONS:
*
* 10-14-92 IanJa        Created.
\***************************************************************************/
VOID
UpdatePerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName)
{
    DWORD dw;
    PQ pq;
    PTHREADINFO  ptiCurrent = PtiCurrent();
    pq = ptiCurrent->pq;

    /*
     * For terminal server, the client is responsible for synchronizing the
     * keyboard state.
     */
    if (gbRemoteSession) {
        return;
    }

    /*
     * Initial Keyboard state (Num-Lock only)
     */
    dw = FastGetProfileIntW(pProfileUserName,
                            PMAP_KEYBOARD,
                            wszInitialKeyboardIndicators,
                            2);

    dw &= 0x80000002;


    /*
     * The special value 0x80000000 in the registry indicates that the BIOS
     * settings are to be used as the initial LED state. (This is undocumented)
     */
    if (dw == 0x80000000) {
        dw = gklpBootTime.LedFlags;
    }
    if (dw & 0x02) {
        SetKeyStateToggle(pq, VK_NUMLOCK);
        SetAsyncKeyStateToggle(VK_NUMLOCK);
        SetRawKeyToggle(VK_NUMLOCK);
    } else {
        ClearKeyStateToggle(pq, VK_NUMLOCK);
        ClearAsyncKeyStateToggle(VK_NUMLOCK);
        ClearRawKeyToggle(VK_NUMLOCK);
    }

    /*
     * Initialize KANA Toggle status
     */
    gfKanaToggle = FALSE;
    ClearKeyStateToggle(pq, VK_KANA);
    ClearAsyncKeyStateToggle(VK_KANA);
    ClearRawKeyToggle(VK_KANA);

    UpdateKeyLights(FALSE);
}
Example #11
0
/***************************************************************************\
* PhkNextValid
*
* This helper routine walk the phkNext chain looking for the next valid
*  hook (i.e., not marked as destroyed). If the end of the local (or
*  thread specific) hook chain is reached, then it jumps to the global
*  (or desktop) chain.
*
* Once a hook is destroyed, we don't want anymore activity on it; however,
*  if the hook is locked at destroy time (= someone is calling it), then
*  we keep it in the list so CallNextHook will work properly
*
* History:
* 03/24/96  GerardoB        Moved to rtl and added *Valid stuff.
* 01-30-91  DavidPe         Created.
\***************************************************************************/
PHOOK PhkNextValid(PHOOK phk)
{

#if DBG
    int iHook = phk->iHook;
#ifdef _USERK_
    CheckCritInShared();
#endif
#endif

    do {
        /*
         * If this hook is marked as destroyed, it must be either
         *  locked or we should be in the process of destroying it
         */
        UserAssert(!(phk->flags & HF_DESTROYED)
                    || (((PHEAD)phk)->cLockObj != 0)
                    || (phk->flags & HF_INCHECKWHF));
        /*
         * Get the next hook
         */
        if (phk->phkNext != NULL) {
            phk = REBASEALWAYS(phk, phkNext);
        } else if (!(phk->flags & HF_GLOBAL)) {
#ifdef _USERK_
            phk = PtiCurrent()->pDeskInfo->aphkStart[phk->iHook + 1];
#else
            PCLIENTINFO pci = GetClientInfo();
            phk = pci->pDeskInfo->aphkStart[phk->iHook + 1];
            /*
             * If it found a pointer, rebase it.
             */
            if (phk != NULL) {
                (KPBYTE)phk -= pci->ulClientDelta;
            }
#endif
            UserAssert((phk == NULL) || (phk->flags & HF_GLOBAL));
        } else {
            return NULL;
        }
        /*
         * If destroyed, keep looking.
         */
    } while ((phk != NULL) && (phk->flags & HF_DESTROYED));

#ifdef _USERK_
    DbgValidateHooks(phk, iHook);
#endif

    return phk;
}
Example #12
0
BOOL _SetTaskmanWindow(PWND pwnd) {

    PDESKTOPINFO pdeskinfo = GETDESKINFO(PtiCurrent());

    if (pwnd != NULL) {
        // Fail the call if another shell window exists
        if (pdeskinfo->spwndTaskman != NULL)
            return(FALSE);
    }

    Lock(&pdeskinfo->spwndTaskman, pwnd);

    return(TRUE);
}
Example #13
0
BOOL xxxPaintRect(
    PWND   pwndBrush,
    PWND   pwndPaint,
    HDC    hdc,
    HBRUSH hbr,
    LPRECT lprc)
{
    POINT ptOrg;

    CheckLock(pwndBrush);
    CheckLock(pwndPaint);

    if (pwndBrush == NULL) {
        pwndBrush = PtiCurrent()->rpdesk->pDeskInfo->spwnd;
    }

    if (pwndBrush == PWNDDESKTOP(pwndBrush)) {
        GreSetBrushOrg(
                hdc,
                0,
                0,
                &ptOrg);
    } else {
        GreSetBrushOrg(
                hdc,
                pwndBrush->rcClient.left - pwndPaint->rcClient.left,
                pwndBrush->rcClient.top - pwndPaint->rcClient.top,
                &ptOrg);
    }

    /*
     * If hbr < CTLCOLOR_MAX, it isn't really a brush but is one of our
     * special color values.  Translate it to the appropriate WM_CTLCOLOR
     * message and send it off to get back a real brush.  The translation
     * process assumes the CTLCOLOR*** and WM_CTLCOLOR*** values map directly.
     */
    if (hbr < (HBRUSH)CTLCOLOR_MAX) {
        hbr = xxxGetControlColor(pwndBrush,
                                 pwndPaint,
                                 hdc,
                                 HandleToUlong(hbr) + WM_CTLCOLORMSGBOX);
    }

    FillRect(hdc, lprc, hbr);

    GreSetBrushOrg(hdc, ptOrg.x, ptOrg.y, NULL);


    return TRUE;
}
Example #14
0
HCURSOR _CreateEmptyCursorObject(
    BOOL fPublic)
{
    PCURSOR pcurT;

    /*
     * Create the cursor object.
     */
    pcurT = (PCURSOR)HMAllocObject(fPublic ? NULL : PtiCurrent(),
                                   NULL,
                                   TYPE_CURSOR,
                                   max(sizeof(CURSOR),
                                   sizeof(ACON)));

    return (HCURSOR)PtoH(pcurT);
}
Example #15
0
/***************************************************************************\
* xxxMessageEvent
*
* Description:  Called when a hooked DDE message is sent or posted.  flags
*   specifies the applicable MF_ flag.  This is called in the server side
*   context of the sender or poster which may or may not be a DDEML process.
*   pdmhd contains DDE data extracted and copied from the client side.
*
* History:
* 12-1-91   sanfords    Created.
\***************************************************************************/
VOID xxxMessageEvent(
PWND pwndTo,
UINT message,
WPARAM wParam,
LPARAM lParam,
DWORD flag,
PDDEML_MSG_HOOK_DATA pdmhd)
{
    PEVENT_PACKET pep;
    PWND pwndFrom;
    TL tlpep;
    PTHREADINFO pti;

    CheckCritIn();

    pep = (PEVENT_PACKET)UserAllocPoolWithQuota(sizeof(EVENT_PACKET) -
            sizeof(DWORD) + sizeof(MONMSGSTRUCT), TAG_DDE8);
    if (pep == NULL) {
        return;
    }
    pep->EventType = flag;
    pep->fSense = TRUE;
    pep->cbEventData = sizeof(MONMSGSTRUCT);
#define pmsgs ((MONMSGSTRUCT *)&pep->Data)
    pmsgs->cb = sizeof(MONMSGSTRUCT);
    pmsgs->hwndTo = PtoH(pwndTo);
    pmsgs->dwTime = NtGetTickCount();

    pwndFrom = RevalidateHwnd((HWND)wParam);
    if (pwndFrom != NULL) {
        pmsgs->hTask = GETPTI(pwndFrom)->pEThread->Cid.UniqueThread;
    } else {
        pmsgs->hTask = 0;
    }

    pmsgs->wMsg = message;
    pmsgs->wParam = wParam;
    pmsgs->lParam = lParam;
    if (pdmhd != NULL) {
        pmsgs->dmhd = *pdmhd;
    }
#undef pmsgs
    pti = PtiCurrent();
    ThreadLockPool(pti, pep, &tlpep);
    xxxCsEvent(pep, sizeof(MONMSGSTRUCT));
    ThreadUnlockAndFreePool(pti, &tlpep);
}
Example #16
0
void
xxxInvalidateDesktopOnPaletteChange(PWND pwnd)
{
    PDESKTOP    pdesk;
    PWND        pwndShell;
    TL          tlpwndShell;
    RECT        rc;
    BOOL        fRedrawDesktop;

    CheckLock(pwnd);

    /*
     * Invalidate the shell window.
     */
    pdesk = PtiCurrent()->rpdesk;
    pwndShell = (pdesk) ? pdesk->pDeskInfo->spwndShell : NULL;
    if (!pwndShell) {
        fRedrawDesktop = TRUE;
        rc = gpsi->rcScreen;
    } else {
        ThreadLockAlways(pwndShell, &tlpwndShell);
        xxxRedrawWindow(
                pwndShell,
                NULL,
                NULL,
                RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);

        /*
         * The shell window may not cover all of the desktop.
         * Invalidate the part of the desktop wallpaper it
         * doesn't sit over.
         */
        fRedrawDesktop = SubtractRect(&rc, &pwnd->rcWindow, &pwndShell->rcWindow);
        ThreadUnlock(&tlpwndShell);
    }

    /*
     * Invalidate the desktop window.
     */
    if (fRedrawDesktop) {
        xxxRedrawWindow(
                pwnd,
                &rc,
                NULL,
                RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
    }
}
Example #17
0
BOOL xxxEndPaint(
    PWND          pwnd,
    LPPAINTSTRUCT lpps)
{
    CheckLock(pwnd);

    ReleaseCacheDC(lpps->hdc, TRUE);

    if (TestWF(pwnd, WFDONTVALIDATE)) {

        if (ghrgnUpdateSave != NULL) {

            InternalInvalidate3(pwnd,
                                ghrgnUpdateSave,
                                RDW_INVALIDATE | RDW_ERASE);

            if (--gnUpdateSave == 0) {
                GreDeleteObject(ghrgnUpdateSave);
                ghrgnUpdateSave = NULL;
            }
        }

        ClrWF(pwnd, WFDONTVALIDATE);
    }

    ClrWF(pwnd, WFWMPAINTSENT);

    /*
     * This used to check that the update-region was empty before
     * doing the clear.  However, this caused a problem with WOW
     * amipro/approach hanging.  They were invalidating rects in
     * their WM_PAINT handler, and allowing the defwindowproc to
     * perform the validation for them.  Since we were blocking
     * the BeginPaint in this case, it sent them into a infinite
     * loop (see bug 19036).
     */
    ClrWF(pwnd, WFSTARTPAINT);

    /*
     * Reshow the caret if needed, but AFTER we've released the DC.
     * This way ShowCaret() can reuse the DC we just released.
     */
    if (pwnd == PtiCurrent()->pq->caret.spwnd)
        zzzInternalShowCaret();

    return TRUE;
}
Example #18
0
BOOL FCallerOk(
    PWND pwnd)
{
    PTHREADINFO pti = PtiCurrent();

    if ((GETPTI(pwnd)->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) &&
            !(pti->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD))) {
        return FALSE;
    }

    if (GETPTI(pwnd)->pEThread->Cid.UniqueProcess == gpidLogon &&
            pti->pEThread->Cid.UniqueProcess != gpidLogon) {
        return FALSE;
    }

    return TRUE;
}
Example #19
0
/***************************************************************************\
* xxxCancelMouseMoveTracking
*
* History
* 12/07/96 GerardoB  Created
\***************************************************************************/
void xxxCancelMouseMoveTracking (DWORD dwDTFlags, PWND pwndTrack, int htEx, DWORD dwDTCancel)
{

    CheckLock(pwndTrack);
    /*
     * Hottracking
     */
    if ((dwDTFlags & DF_HOTTRACKING) && (dwDTCancel & DF_HOTTRACKING)) {
        /*
         * The current state must be owned by the current queue.
         * Otherwise, we're about to do an inter-queue cancelation.
         */
        UserAssert(PtiCurrent()->pq == GETPTI(pwndTrack)->pq);

        xxxHotTrack(pwndTrack, htEx, FALSE);
    }

    /*
     * Tooltips
     */
    if ((dwDTFlags & DF_TOOLTIPSHOWING) && (dwDTCancel & DF_TOOLTIP)) {
        PTOOLTIPWND pttwnd = (PTOOLTIPWND)PWNDTOOLTIP(pwndTrack);
        TL tlpwnd;

        ThreadLockAlways(pttwnd, &tlpwnd);
        xxxResetTooltip(pttwnd);
        ThreadUnlock(&tlpwnd);
    }

    /*
     * Mouse Leave
     */
    if ((dwDTFlags & DF_TRACKMOUSELEAVE) && (dwDTCancel & DF_TRACKMOUSELEAVE)) {
        _PostMessage(pwndTrack,
                     ((htEx == HTCLIENT) ? WM_MOUSELEAVE : WM_NCMOUSELEAVE),
                     0, 0);
    }

    /*
     * Mouse Hover
     */
    if ((dwDTFlags & DF_TRACKMOUSEHOVER) && (dwDTCancel & DF_TRACKMOUSEHOVER)) {
        _KillSystemTimer(pwndTrack, IDSYS_MOUSEHOVER);
    }
}
Example #20
0
BOOL _UnregisterHotKey(
    PWND pwnd,
    int id)
{
    PHOTKEY phk;
    BOOL fKeysExist;

    phk = FindHotKey(PtiCurrent(), pwnd, id, 0, 0, TRUE, &fKeysExist);

    /*
     * No hotkey to unregister, return FALSE.
     */
    if (phk == NULL) {
        RIPERR0(ERROR_HOTKEY_NOT_REGISTERED, RIP_VERBOSE, "");
        return FALSE;
    }

    return TRUE;
}
Example #21
0
/***************************************************************************\
* MNAllocMenuState
*
* Allocates and initializes a pMenuState
*
* 5-21-96 GerardoB      Created
\***************************************************************************/
PMENUSTATE MNAllocMenuState(PTHREADINFO ptiCurrent, PTHREADINFO ptiNotify, PPOPUPMENU ppopupmenuRoot)
{
    PMENUSTATE pMenuState;

    UserAssert(PtiCurrent() == ptiCurrent);
    UserAssert(ptiCurrent->rpdesk == ptiNotify->rpdesk);

    /*
     * If gpMenuState is already taken, allocate one.
     */
    if (gfMenuStateInUse) {
        pMenuState = (PMENUSTATE)UserAllocPoolWithQuota(sizeof(MENUSTATE), TAG_MENUSTATE);
        if (pMenuState == NULL) {
            return NULL;
        }
    } else {
        gfMenuStateInUse = TRUE;
        pMenuState = &gpMenuState;
    }

    /*
     * This is used by IsSomeOneInMenuMode and for debugging purposes
     */
    guMenuStateCount++;

    /*
     * Initialize pMenuState.
     */
    RtlZeroMemory(pMenuState, sizeof(*pMenuState));
    pMenuState->pGlobalPopupMenu = ppopupmenuRoot;
    pMenuState->ptiMenuStateOwner = ptiCurrent;
    UserAssert(ptiCurrent->pMenuState == NULL);
    ptiCurrent->pMenuState = pMenuState;
    if (ptiNotify != ptiCurrent) {
        UserAssert(ptiNotify->pMenuState == NULL);
        ptiNotify->pMenuState = pMenuState;
    }


    return pMenuState;

}
Example #22
0
VOID UserRedrawDesktop(VOID)
{
    TL   tlpwnd;
    PWND pwndDesk;

    EnterCrit();

    pwndDesk = PtiCurrent()->rpdesk->pDeskInfo->spwnd;

    ThreadLockAlways(pwndDesk, &tlpwnd);

    xxxInternalInvalidate(pwndDesk,
                          HRGN_FULL,
                          RDW_INVALIDATE |
                              RDW_ERASE  |
                              RDW_FRAME  |
                              RDW_ALLCHILDREN);

    ThreadUnlock(&tlpwnd);

    LeaveCrit();
}
Example #23
0
VOID xxxSimpleDoSyncPaint(
    PWND pwnd)
{
    HRGN  hrgnUpdate;
    DWORD flags = 0;

    CheckLock(pwnd);

    /*
     * Since we're taking care of the frame drawing, we can consider
     * this WM_PAINT message processed.
     */
    ClrWF(pwnd, WFPAINTNOTPROCESSED);

    /*
     * Make copies of these flags, because their state might
     * change after we send a message, and we don't want
     * to "lose" them.
     */
    if (TestWF(pwnd, WFSENDNCPAINT))
        flags |= DSP_FRAME;

    if (TestWF(pwnd, WFSENDERASEBKGND))
        flags |= DSP_ERASE;

    if (flags & (DSP_ERASE | DSP_FRAME)) {

        if (!TestWF(pwnd, WFVISIBLE)) {

            /*
             * If there is no update region, just clear the bits.
             */
            ClrWF(pwnd, WFSENDNCPAINT);
            ClrWF(pwnd, WFSENDERASEBKGND);
            ClrWF(pwnd, WFPIXIEHACK);
            ClrWF(pwnd, WFERASEBKGND);
            ClearHungFlag(pwnd, WFREDRAWIFHUNG);

        } else {

            PTHREADINFO ptiCurrent = PtiCurrent();

            /*
             * If there is no update region, we don't have to
             * do any erasing, but we may need to send an NCPAINT.
             */
            if (pwnd->hrgnUpdate == NULL) {
                ClrWF(pwnd, WFSENDERASEBKGND);
                ClrWF(pwnd, WFERASEBKGND);
                flags &= ~DSP_ERASE;
            }

            /*
             * Only mess with windows owned by the current thread.
             * NOTE: This means that WM_NCPAINT and WM_ERASEBKGND are
             *       only sent intra-thread.
             */
            if (GETPTI(pwnd) == ptiCurrent) {

                hrgnUpdate = GetNCUpdateRgn(pwnd, TRUE);

                if (flags & DSP_FRAME) {

                    /*
                     * If the message got sent before we got here then do
                     * nothing.
                     */
                    if (TestWF(pwnd, WFSENDNCPAINT))
                        xxxSendNCPaint(pwnd, hrgnUpdate);
                }

                if (flags & DSP_ERASE) {

                    if (TestWF(pwnd, WFSENDNCPAINT)) {
                        /*
                         * If we got another invalidate during the NCPAINT
                         * callback get the new update region
                         */
                        DeleteMaybeSpecialRgn(hrgnUpdate);
                        hrgnUpdate = GetNCUpdateRgn(pwnd, FALSE);
                    }

                    /*
                     * If the message got sent before we got here
                     * (e.g.: an UpdateWindow() inside WM_NCPAINT handler,
                     * for example), don't do anything.
                     *
                     * WINPROJ.EXE (version 1.0) calls UpdateWindow() in
                     * the WM_NCPAINT handlers for its subclassed listboxes
                     * in the open dialog.
                     */
                    if (TestWF(pwnd, WFSENDERASEBKGND)) {
                        ClrWF(pwnd, WFSENDERASEBKGND);
                        ClrWF(pwnd, WFERASEBKGND);
                        xxxSendEraseBkgnd(pwnd, NULL, hrgnUpdate);
                    }

                    /*
                     * The erase and frame operation has occured. Clear the
                     * WFREDRAWIFHUNG bit here. We don't want to clear it until we
                     * know the erase and frame has occured, so we know we always
                     * have a consistent looking window.
                     */
                    ClearHungFlag(pwnd, WFREDRAWIFHUNG);
                }

                DeleteMaybeSpecialRgn(hrgnUpdate);

            } else if (!TestwndChild(pwnd)                         &&
                       (pwnd != grpdeskRitInput->pDeskInfo->spwnd) &&
                       FHungApp(GETPTI(pwnd), CMSHUNGAPPTIMEOUT)   &&
                       TestWF(pwnd, WFREDRAWIFHUNG)) {

                ClearHungFlag(pwnd, WFREDRAWIFHUNG);
                xxxRedrawHungWindow(pwnd, NULL);
            }
        }
    }
}
Example #24
0
BOOL DoPaint(
    PWND  pwndFilter,
    LPMSG lpMsg)
{
    PWND        pwnd;
    PWND        pwndT;
    PTHREADINFO ptiCurrent = PtiCurrent();


#if 0 // CHRISWIL: WIN95 SPECIFIC

    /*
     * If there is a system modal up and it is attached to another task,
     * DON'T do paints.  We don't want to return a message for a window in
     * another task!
     */
    if (hwndSysModal && (hwndSysModal->hq != hqCurrent)) {

        /*
         * Poke this guy so he wakes up at some point in the future,
         * otherwise he may never wake up to realize he should paint.
         * Causes hangs - e.g. Photoshop installation program
         *   PostThreadMessage32(Lpq(hqCurrent)->idThread, WM_NULL, 0, 0, 0);
         */
        return FALSE;
    }

#endif

    /*
     * If this is a system thread, then walk the windowstation desktop-list
     * to find the window which needs painting.  For other threads, we
     * reference off the thread-desktop.
     */
    if (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD) {

        PWINDOWSTATION pwinsta;
        PDESKTOP       pdesk;

        if ((pwinsta = ptiCurrent->pwinsta) == NULL) {
            RIPMSG0(RIP_ERROR, "DoPaint: SYSTEMTHREAD does not have (pwinsta)");
            return FALSE;
        }

        pwnd = NULL;
        for(pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {

            if (pwnd = InternalDoPaint(pdesk->pDeskInfo->spwnd, ptiCurrent))
                break;
        }

    } else {
        pwnd = InternalDoPaint(ptiCurrent->rpdesk->pDeskInfo->spwnd,
                               ptiCurrent);
    }

    if (pwnd != NULL) {

        if (!CheckPwndFilter(pwnd, pwndFilter))
            return FALSE;

        /*
         * We're returning a WM_PAINT message, so clear WFINTERNALPAINT so
         * it won't get sent again later.
         */
        if (TestWF(pwnd, WFINTERNALPAINT)) {

            ClrWF(pwnd, WFINTERNALPAINT);

            /*
             * If there is no update region, then no more paint for this
             * window.
             */
            if (pwnd->hrgnUpdate == NULL)
                DecPaintCount(pwnd);
        }

        /*
         * Set the STARTPAINT so that any other calls to BeginPaint while
         * painting is begin performed, will prevent painting on those
         * windows.
         *
         * Clear the UPDATEDIRTY since some apps (DBFast) don't call
         * GetUpdateRect, BeginPaint/EndPaint.
         */
        ClrWF(pwnd, WFSTARTPAINT);
        ClrWF(pwnd, WFUPDATEDIRTY);

        /*
         * If we get an invalidate between now and the time the app calls
         * BeginPaint() and the windows parent is not CLIPCHILDREN, then
         * the parent will paint in the wrong order.  So we are going to
         * cause the child to paint again.  Look in beginpaint and internal
         * invalidate for other parts of this fix.
         *
         * Set a flag to signify that we are in the bad zone.
         *
         * Must go up the parent links to make sure all parents have
         * WFCLIPCHILDREN set otherwise set the WFWMPAINTSENT flag.
         * This is to fix Excel spreadsheet and fulldrag. The speadsheet
         * parent window (class XLDESK) has WFCLIPCHILDREN set but it's
         * parent (class XLMAIN) doesn't. So the main window erases  the
         * background after the child window paints.
         *
         * JOHANNEC : 27-Jul-1994
         */
        
        /*
         * NT Bug 400167: As we walk up the tree, we need to stop short of
         * desktop windows and mother desktop windows.  We can't do a test
         * for WFCLIPCHILDREN on the mother desktop window's parent because
         * it doesn't exist.  This means that no desktop window will get 
         * WFWMPAINTSENT set, but the message window will be able to get 
         * WFWMPAINTSENT set.
         */
        
        pwndT = pwnd;
        while (pwndT && (GETFNID(pwndT) != FNID_DESKTOP)) {

            if (!TestWF(pwndT->spwndParent, WFCLIPCHILDREN)) {
                SetWF(pwnd, WFWMPAINTSENT);
                break;
            }

            pwndT = pwndT->spwndParent;
        }

        /*
         * If the top level "tiled" owner/parent of this window is iconed,
         * send a WM_PAINTICON rather than a WM_PAINT.  The wParam
         * is TRUE if this is the tiled window and FALSE if it is a
         * child/owned popup of the minimized window.
         *
         * BACKWARD COMPATIBILITY HACK
         *
         * 3.0 sent WM_PAINTICON with wParam == TRUE for no apparent
         * reason.  Lotus Notes 2.1 depends on this for some reason
         * to properly change its icon when new mail arrives.
         */
        if (!TestWF(pwnd, WFWIN40COMPAT) &&
            TestWF(pwnd, WFMINIMIZED)    &&
            (pwnd->pcls->spicn != NULL)) {

            StoreMessage(lpMsg, pwnd, WM_PAINTICON, (DWORD)TRUE, 0L, 0L);

        } else {

            StoreMessage(lpMsg, pwnd, WM_PAINT, 0, 0L, 0L);
        }

        return TRUE;
    }

    return FALSE;
}
Example #25
0
HDC xxxBeginPaint(
    PWND          pwnd,
    LPPAINTSTRUCT lpps)
{
    HRGN hrgnUpdate;
    HDC  hdc;
    BOOL fSendEraseBkgnd;

    CheckLock(pwnd);
    UserAssert(IsWinEventNotifyDeferredOK());

    if (TEST_PUDF(PUDF_DRAGGINGFULLWINDOW))
        SetWF(pwnd, WFSTARTPAINT);

    /*
     * We're processing a WM_PAINT message: clear this flag.
     */
    ClrWF(pwnd, WFPAINTNOTPROCESSED);

    /*
     * If this bit gets set while we are drawing the frame we will need
     * to redraw it.
     *
     * If necessary, send our WM_NCPAINT message now.
     *
     * please heed these notes
     *
     * We have to send this message BEFORE we diddle hwnd->hrgnUpdate,
     * because an app may call ValidateRect or InvalidateRect in its
     * handler, and it expects what it does to affect what gets drawn
     * in the later WM_PAINT.
     *
     * It is possible to get an invalidate when we leave the critical
     * section below, therefore we loop until UPDATEDIRTY is clear
     * meaning there were no additional invalidates.
     */
    if (TestWF(pwnd, WFSENDNCPAINT)) {

        do {
            ClrWF(pwnd, WFUPDATEDIRTY);
            hrgnUpdate = GetNCUpdateRgn(pwnd, FALSE);
            xxxSendNCPaint(pwnd, hrgnUpdate);
            DeleteMaybeSpecialRgn(hrgnUpdate);
        } while (TestWF(pwnd, WFUPDATEDIRTY));

    } else {
        ClrWF(pwnd, WFUPDATEDIRTY);
    }

    /*
     * Hide the caret if needed.  Do this before we get the DC so
     * that if HideCaret() gets and releases a DC we will be able
     * to reuse it later here.
     * No need to DeferWinEventNotify() since pwnd is locked.
     */
    if (pwnd == PtiCurrent()->pq->caret.spwnd)
        zzzInternalHideCaret();

    /*
     * Send the check for sending an WM_ERASEBKGND to the
     * window.
     */
    if (fSendEraseBkgnd = TestWF(pwnd, WFSENDERASEBKGND)) {
        ClrWF(pwnd, WFERASEBKGND);
        ClrWF(pwnd, WFSENDERASEBKGND);
    }

    /*
     * Validate the entire window.
     */
    if (NEEDSPAINT(pwnd))
        DecPaintCount(pwnd);

    ClrWF(pwnd, WFINTERNALPAINT);

    hrgnUpdate = pwnd->hrgnUpdate;
    pwnd->hrgnUpdate = NULL;

    if (TestWF(pwnd, WFDONTVALIDATE)) {

        if (ghrgnUpdateSave == NULL) {
            ghrgnUpdateSave = CreateEmptyRgn();
        }

        if (ghrgnUpdateSave != NULL) {
            UnionRgn(ghrgnUpdateSave, ghrgnUpdateSave, hrgnUpdate);
            gnUpdateSave++;
        }
    }

    /*
     * Clear these flags for backward compatibility
     */
    lpps->fIncUpdate =
    lpps->fRestore   = FALSE;

    lpps->hdc =
    hdc       = _GetDCEx(pwnd,
                         hrgnUpdate,
                         DCX_USESTYLE | DCX_INTERSECTRGN);

    if (UT_GetParentDCClipBox(pwnd, hdc, &lpps->rcPaint)) {

        /*
         * If necessary, erase our background, and possibly deal with
         * our children's frames and backgrounds.
         */
        if (fSendEraseBkgnd)
            xxxSendEraseBkgnd(pwnd, hdc, hrgnUpdate);
    }

    /*
     * Now that we're completely erased, see if there are any children
     * that couldn't draw their own frames because their update regions
     * got deleted.
     */
    xxxSendChildNCPaint(pwnd);

    /*
     * The erase and frame operation has occured. Clear the WFREDRAWIFHUNG
     * bit here. We don't want to clear it until we know the erase and
     * frame has occured, so we know we always have a consistent looking
     * window.
     */
    ClearHungFlag(pwnd, WFREDRAWIFHUNG);

    lpps->fErase = (TestWF(pwnd, WFERASEBKGND) != 0);

    return hdc;
}
Example #26
0
VOID xxxInternalDoSyncPaint(
    PWND  pwnd,
    DWORD flags)
{
    CheckLock(pwnd);

    /*
     * Do the paint for this window.
     */
    xxxSimpleDoSyncPaint(pwnd);

    /*
     * Normally we like to enumerate all of this window's children and have
     * them erase their backgrounds synchronously.  However, this is a bad
     * thing to do if the window is NOT CLIPCHLIDREN.  Here's the scenario
     * we want to to avoid:
     *
     * 1) Window 'A' is invalidated
     * 2) 'A' erases itself (or not, doesn't matter)
     * 3) 'A's children are enumerated and they erase themselves.
     * 4) 'A' paints over its children (remember, 'A' isn't CLIPCHILDREN)
     * 5) 'A's children paint but their backgrounds aren't their ERASEBKND
     *    color (because 'A' painted over them) and everything looks like
     *    dirt.
     */
    if ((flags & DSP_ALLCHILDREN) ||
        ((flags & DSP_ENUMCLIPPEDCHILDREN) && TestWF(pwnd, WFCLIPCHILDREN))) {

        TL   tlpwnd;
        PBWL pbwl;
        HWND *phwnd;

        if (pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL)) {

            PTHREADINFO ptiCurrent = PtiCurrent();
            HWND        hwnd;

            /*
             * If the client dies during a callback, the hwnd list
             * will be freed in xxxDestroyThreadInfo.
             */
            for (phwnd = pbwl->rghwnd; (hwnd = *phwnd) != (HWND)1; phwnd++) {

                if (hwnd == NULL)
                    continue;

                if ((pwnd = (PWND)RevalidateHwnd(hwnd)) == NULL)
                    continue;

                /*
                 * Note: testing if a window is a child automatically
                 * excludes the desktop window.
                 */
                if (TestWF(pwnd, WFCHILD) && (ptiCurrent != GETPTI(pwnd))) {

                    /*
                     * Don't cause any more intertask sendmessages cause it
                     * does bad things to cbt's windowproc hooks.  (Due to
                     * SetParent allowing child windows in the topwindow
                     * hierarchy.
                     */
                    continue;
                }

                /*
                 * Note that we pass only certain bits down as we recurse:
                 * the other bits pertain to the current window only.
                 */
                ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
                xxxInternalDoSyncPaint(pwnd, flags);
                ThreadUnlock(&tlpwnd);
            }

            FreeHwndList(pbwl);
        }
    }
}
Example #27
0
void xxxEndMenu(
    PMENUSTATE pMenuState)
{
    BOOL fMenuStateOwner;
    PPOPUPMENU  ppopup;
    PTHREADINFO ptiCurrent;

    if ((ppopup = pMenuState->pGlobalPopupMenu) == NULL) {

        /*
         * We're not really in menu mode. This can happen
         *  if we are forced out of menu loop too soon; i.e, from
         *  inside xxxMNGetPopup or xxxTrackPopupMenuEx.
         */
         UserAssert(!pMenuState->fInsideMenuLoop && !pMenuState->fMenuStarted);
        return;
    }



    pMenuState->fInsideMenuLoop = FALSE;
    pMenuState->fMenuStarted = FALSE;
    /*
     * Mark the popup as destroyed so people will not use it anymore.
     * This means that root popups can be marked as destroyed before
     * actually being destroyed (nice and confusing).
     */
    ppopup->fDestroyed = TRUE;

    /*
     * Determine if this is the menu loop owner before calling back.
     * Only the owner can destroy the menu windows
     */
   ptiCurrent = PtiCurrent();
   fMenuStateOwner = (ptiCurrent == pMenuState->ptiMenuStateOwner);

    /*
     * Release mouse capture if we got it in xxxStartMenuState
     */
    if (ptiCurrent->pq->spwndCapture == pMenuState->pGlobalPopupMenu->spwndNotify) {
        xxxMNReleaseCapture();
    }

    /*
     * Bail if this is not the menu loop owner
     */
    if (!fMenuStateOwner) {
        RIPMSG1(RIP_WARNING, "xxxEndMenu: Thread %#p doesn't own the menu loop", ptiCurrent);
        return;
    }
    /*
     * If the menu loop is running on a thread different than the thread
     *  that owns spwndNotify, we can have two threads trying to end
     *  this menu at the same time.
     */
    if (pMenuState->fInEndMenu) {
        RIPMSG1(RIP_WARNING, "xxxEndMenu: already in EndMenu. pMenuState:%#p", pMenuState);
        return;
    }
    pMenuState->fInEndMenu = TRUE;

    if (pMenuState->pGlobalPopupMenu->spwndNotify != NULL) {
        if (!pMenuState->pGlobalPopupMenu->fInCancel) {
            xxxMNDismiss(pMenuState);
        }
    } else {
        BOOL    fTrackedPopup = ppopup->fIsTrackPopup;

        /*
         * This should do the same stuff as MenuCancelMenus but not send any
         * messages...
         */
        xxxMNCloseHierarchy(ppopup, pMenuState);

        if (fTrackedPopup) {
            xxxDestroyWindow(ppopup->spwndPopupMenu);
        }

    }

}
Example #28
0
BOOL _TranslateMessage(
    LPMSG pmsg,
    UINT flags)
{
    PTHREADINFO pti;
    UINT wMsgType;
    WORD *pwParam;
    int cChar;
    BOOL fSysKey = FALSE;
    BOOL bBreak;
    LPARAM lParam;

    switch (pmsg->message) {

    default:
        return FALSE;

    case WM_SYSKEYDOWN:
        /*
         * HACK carried over from Win3 code: system messages
         * only get posted during KEYDOWN processing - so
         * set fSysKey only for WM_SYSKEYDOWN.
         */
        fSysKey = TRUE;
        /*
         * Fall thru...
         */

    case WM_SYSKEYUP:
    case WM_KEYDOWN:
    case WM_KEYUP:
        pti = PtiCurrent();

        if ((pti->pMenuState != NULL) &&
                (HW(pti->pMenuState->pGlobalPopupMenu->spwndPopupMenu) ==
                pmsg->hwnd)) {
            flags |= 1;
        } else {
            flags &= ~1;
        }

        /*
         * Don't change the contents of the passed in structure.
         */
        lParam = pmsg->lParam;

        cChar = InternalToUnicode(LOWORD(pmsg->wParam),  // virtual key code
                         HIWORD(lParam),  // scan code, make/break bit
                         pti->pq->afKeyState,
                         pState, 16,  // see init.c
                         flags, &bBreak);

/*
 * LATER 12/7/90 - GregoryW
 * Note: Win3.x TranslateMessage returns TRUE if ToAscii is called.
 *       Proper behavior is to return TRUE if any translation is
 *       performed by ToAscii.  If we have to remain compatible
 *       (even though apps clearly don't currently care about the
 *       return value) then the following return should be changed
 *       to TRUE.  If we want the new 32-bit apps to have a meaningful
 *       return value we should leave this as FALSE.
 *
 *      If console is calling us with the TM_POSTCHARBREAKS flag then we
 *      return FALSE if no char was actually posted
 *
 *      !!! LATER get console to change so it does not need private API
 *      TranslateMessageEx
 */

        if (!cChar) {
            if (flags & TM_POSTCHARBREAKS)
                return FALSE;
            else
                return TRUE;
        }

        /*
         * Some translation performed.  Figure out what type of
         * message to post.
         *
         */
        if (cChar > 0)
            wMsgType = (fSysKey) ? (UINT)WM_SYSCHAR : (UINT)WM_CHAR;
        else {
            wMsgType = (fSysKey) ? (UINT)WM_SYSDEADCHAR : (UINT)WM_DEADCHAR;
            cChar = -cChar;                // want positive value
        }

        if (bBreak) {
            lParam |=  0x80000000;
        } else {
            lParam &= ~0x80000000;
        }

        pwParam = (WORD *)pState;

        for ( ; cChar > 0; cChar--) {

            /*
             * If this is a multi-character posting, all but the last one
             * should be marked as fake keystrokes for Console/VDM.
             */

            _PostMessage(PW(pmsg->hwnd), wMsgType, (DWORD)*pwParam,
                    lParam | (cChar > 1 ? FAKE_KEYSTROKE : 0));

            *pwParam = 0;        // zero out old character
            pwParam += 1;
        }

        return TRUE;
    }
}
Example #29
0
BOOL xxxShowWindow(
    PWND pwnd,
    DWORD cmdShowAnimate)
{
    BOOL fVisOld, fVisNew;
    UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE;
    PTHREADINFO pti;
    BOOL bFirstMain = FALSE;
    int cmdShow = LOWORD(cmdShowAnimate);

    CheckLock(pwnd);

    fVisOld = TestWF(pwnd, WFVISIBLE);
    pti = PtiCurrent();

    /*
     * See if this is the first "main" top level
     * window being created by this application - if show, assume it
     * is showing with the SW_SHOWDEFAULT command.
     *
     * Checks for:
     * - cmdShow is a "default" show command
     * - we haven't done startupinfo yet (we only use it once)
     * - this is not a child (it is a top level window)
     * - this has a titlebar (indicator of the main window)
     * - it isn't owned (indicator of the main window)
     */
    if ((pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) &&
            !TestwndChild(pwnd) &&
            (TestWF(pwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFCAPTION)) &&
            (pwnd->spwndOwner == NULL)) {

        bFirstMain = TRUE;

        switch (cmdShow) {
        case SW_SHOWNORMAL:
        case SW_SHOW:

            /*
             * Then assume default!
             */
            cmdShow = SW_SHOWDEFAULT;
            break;
        }
    }

    /*
     * If this application specified SW_SHOWDEFAULT, then we get the
     * real SW_* command from the application's STARTUPINFO structure
     * (STARTUPINFO is passed to CreateProcess() when this application
     * was launched).
     */
    if (cmdShow == SW_SHOWDEFAULT) {

        /*
         * Call the client to get the SW_* command from the STARTUPINFO
         * for this process.
         */
        if (pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) {

            bFirstMain = TRUE;

            cmdShow = pti->ppi->usi.wShowWindow;
#if 0
            switch (cmdShow) {
            case SW_SHOWMINIMIZED:
            case SW_MINIMIZE:

                /*
                 * If the default show was "minimized", then make sure it doesn't
                 * become active.  Minimized is effectively "background".
                 */
                cmdShow = SW_SHOWMINNOACTIVE;
                break;
            }
#endif
        }
    }

    //
    // This is in case someone said SW_SHOWDEFAULT but has no startupinfo.
    // Or in case cmdShow inside of STARTUPINFO is SW_SHOWDEFAULT.
    //
    if (cmdShow == SW_SHOWDEFAULT)
        cmdShow = SW_SHOWNORMAL;

    /*
     * Turn off startup info.  We turn this off after the first call to
     * ShowWindow.  If we don't apps can be started by progman with
     * the start info being minimized and then be restored and then
     * call ShowWindow(SW_SHOW) and the app would minimize again.
     * Notepad had that problem 2985.
     */
    if (bFirstMain) {
        pti->ppi->usi.dwFlags &= ~(STARTF_USESHOWWINDOW|STARTF_USESIZE \
                | STARTF_USEPOSITION);
    }


    /*
     * Take care of all the OLD show commands with columns & iconslot.
     */
    if (cmdShow & 0xFF00) {
        if ((cmdShow & 0xFF80) == (int)0xFF80)
            cmdShow = SW_SHOWMINNOACTIVE;
        else
            cmdShow = SW_SHOW;
    }

    /*
     * Change to new fullscreen if needed and in same desktop
     */
    if ((pwnd->bFullScreen != WINDOWED)
            && (pwnd->head.rpdesk == grpdeskRitInput)) {
        if ((cmdShow == SW_SHOWNORMAL) ||
            (cmdShow == SW_RESTORE) ||
            (cmdShow == SW_MAXIMIZE) ||
            (cmdShow == SW_SHOWMAXIMIZED)) {
            cmdShow = SW_SHOWMINIMIZED;

            if (pwnd->bFullScreen == FULLSCREENMIN) {
                pwnd->bFullScreen = FULLSCREEN;
            }

            if (gpqForeground != NULL &&
                gpqForeground->spwndActive == pwnd) {
                xxxMakeWindowForegroundWithState(NULL, 0);
            }
        }
    }

    switch (cmdShow) {
    case SW_SHOWNOACTIVATE:
    case SW_SHOWNORMAL:
    case SW_RESTORE:

        /*
         * If min/max, let xxxMinMaximize() do all the work.
         */
        if (TestWF(pwnd, WFMINIMIZED) || TestWF(pwnd, WFMAXIMIZED)) {
            xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
            return fVisOld;

        } else {

            /*
             * Ignore if the window is already visible.
             */
            if (fVisOld) {
                return fVisOld;
            }

            swpFlags |= SWP_SHOWWINDOW;
            if (   cmdShow == SW_SHOWNOACTIVATE) {
                swpFlags |= SWP_NOZORDER;
#ifdef NEVER
                /*
                 * This is what win3.1 does. On NT, since each "queue" has
                 * its own active window, there is often no active window.
                 * In this case, win3.1 turns a SHOWNOACTIVATE into a "SHOW
                 * with activate". Since win3.1 almost always has an active
                 * window, this almost never happens. So on NT, we're not
                 * going to do this check - that way we'll be more compatible
                 * with win3.1 because we'll usally not activate (like win3.1).
                 * With this check, this causes FoxPro 2.5 for Windows to not
                 * properly activate its command window when first coming up.
                 */
                if (pti->pq->spwndActive != NULL)
                    swpFlags |= SWP_NOACTIVATE;
#else
                swpFlags |= SWP_NOACTIVATE;
#endif
            }
        }
        break;

    case SW_SHOWMINNOACTIVE:
    case SW_SHOWMINIMIZED:
    case SW_SHOWMAXIMIZED:
    case SW_MINIMIZE:
        xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
        return fVisOld;

    case SW_SHOWNA:
        swpFlags |= SWP_SHOWWINDOW | SWP_NOACTIVATE;

        // LATER removed this to be compatible with SHOWNOACTIVATE
        //if (pti->pq->spwndActive != NULL)
        //    swpFlags |= SWP_NOACTIVATE;
        break;

    case SW_SHOW:

        /*
         * Don't bother if it is already visible.
         */
        if (fVisOld)
            return fVisOld;

        swpFlags |= SWP_SHOWWINDOW;
        if (cmdShow == SW_SHOWNOACTIVATE)
        {
            swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE;
        }
        break;

    case SW_HIDE:

        /*
         * Don't bother if it is already hidden.
         */
        if (!fVisOld)
            return fVisOld;

        swpFlags |= SWP_HIDEWINDOW;
        if (pwnd != pti->pq->spwndActive)
            swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
        break;

    default:
        RIPERR0(ERROR_INVALID_SHOWWIN_COMMAND, RIP_VERBOSE, "");
        return fVisOld;
    }

    /*
     * If we're changing from visible to hidden or vise-versa, send
     * WM_SHOWWINDOW.
     */
    fVisNew = !(cmdShow == SW_HIDE);
    if (fVisNew != fVisOld) {
        xxxSendMessage(pwnd, WM_SHOWWINDOW, fVisNew, 0L);
        if (!TestWF(pwnd, WFWIN31COMPAT)) {
            xxxSendMessage(pwnd, WM_SETVISIBLE, fVisNew, 0L);
        }
    }

    if (!TestwndChild(pwnd)) {
        if (TestCF(pwnd, CFSAVEBITS)) {

            /*
             * Activate to prevent discarding saved bits???
             */
            if (cmdShow == SW_SHOW || cmdShow == SW_SHOWNORMAL) {
                xxxActivateWindow(pwnd, AW_USE);
                swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE;
            }
        }
    } else {

        /*
         * Children can't get activation...
         */
        swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
    }

    /*
     * If our parent is hidden, don't bother to call xxxSetWindowPos.
     */
    if (_FChildVisible(pwnd)) {
        xxxSetWindowPos(pwnd, (PWND)NULL, 0, 0, 0, 0, swpFlags);
    } else {
        if (cmdShow == SW_HIDE)
            ClrWF(pwnd, WFVISIBLE);
        else
            SetWF(pwnd, WFVISIBLE);
    }

    /*
     * Send size and move messages AFTER repainting
     */
    if (TestWF(pwnd, WFSENDSIZEMOVE)) {
        ClrWF(pwnd, WFSENDSIZEMOVE);
        if (TestWF(pwnd, WFMINIMIZED)) {
            xxxSendSizeMessage(pwnd, SIZEICONIC);
        } else if (TestWF(pwnd, WFMAXIMIZED)) {
            xxxSendSizeMessage(pwnd, SIZEFULLSCREEN);
        } else {
            xxxSendSizeMessage(pwnd, SIZENORMAL);
        }
        if (pwnd->spwndParent) {
            xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG(
                    pwnd->rcClient.left - pwnd->spwndParent->rcClient.left,
                    pwnd->rcClient.top - pwnd->spwndParent->rcClient. top));
        } else {
            /*
             * NULL parent implies this window is a zombie
             */
            xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG(
                    pwnd->rcClient.left, pwnd->rcClient.top));
        }
    }

    /*
     * If hiding and is active-foreground window, activate someone else.
     * If hiding a active window make someone active.
     */
    if (cmdShow == SW_HIDE) {
        if ((pwnd == pti->pq->spwndActive) && (pti->pq == gpqForeground)) {
            xxxActivateWindow(pwnd, AW_SKIP);
        } else {
            xxxCheckFocus(pwnd);
        }
    }

    return fVisOld;
}
Example #30
0
BOOL xxxSendEraseBkgnd(
    PWND pwnd,
    HDC  hdcBeginPaint,
    HRGN hrgnUpdate)
{
    PTHREADINFO ptiCurrent;
    BOOL        fErased;
    HDC         hdc;

    CheckLock(pwnd);

    /*
     * For minimized dudes in win3.1, we would've sent an
     * WM_ICONERASEBKGND and cleared the erase bit.  Now that min
     * windows in 4.0 are all nonclient, don't bother erasing at
     * all.  Pretend like we did.
     *
     * NOTE:
     * For < 4.0 windows, we may have to send a fake WM_ICONERASEKBGND
     * to keep 'em happy.  Saves time not to though.  Getting a DC and
     * sending the message ain't speedy.
     */
    if ((hrgnUpdate == NULL) || TestWF(pwnd, WFMINIMIZED))
        return FALSE;

    /*
     * If a DC to use was not passed in, get one.
     * We want one clipped to this window's update region.
     */
    if (hdcBeginPaint == NULL) {

       hdc = _GetDCEx(pwnd,
                      hrgnUpdate,
                      DCX_USESTYLE | DCX_INTERSECTRGN | DCX_NODELETERGN);
    } else {

        hdc = hdcBeginPaint;
    }

    /*
     * If we're send the WM_ERASEBKGND to another process
     * we need to change the DC owner.
     *
     * We'd like to change the owner to pwnd->pti->idProcess, but
     * GDI won't let us assign ownership back to ourselves later.
     */
    ptiCurrent = PtiCurrent();

    if (GETPTI(pwnd)->ppi != ptiCurrent->ppi)
        GreSetDCOwner(hdc, OBJECT_OWNER_PUBLIC);

    /*
     * Send the event to the window.  This contains the DC clipped to
     * the update-region.
     */
    fErased = (BOOL)xxxSendMessage(pwnd, WM_ERASEBKGND, (WPARAM)hdc, 0L);

    /*
     * If we've changed the DC owner, change it back to
     * the current process.
     */
    if (GETPTI(pwnd)->ppi != ptiCurrent->ppi)
        GreSetDCOwner(hdc, OBJECT_OWNER_CURRENT);

    /*
     * If the WM_ERASEBKGND message did not erase the
     * background, then set this flag to let BeginPaint()
     * know to ask the caller to do it via the fErase
     * flag in the PAINTSTRUCT.
     */
    if (!fErased) {
        SetWF(pwnd, WFERASEBKGND);
        if (!TestWF(pwnd, WFWIN31COMPAT))
            SetWF(pwnd, WFSENDERASEBKGND);
    }

    /*
     * If we got a cache DC in this routine, release it.
     */
    if (hdcBeginPaint == NULL) {
        ReleaseCacheDC(hdc, TRUE);
    }

    return fErased;
}