test: mnstate.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# mnstate.c File Reference

`#include "precomp.h"`

Go to the source code of this file.

## Functions

PMENU | xxxGetInitMenuParam (PWND pwndMenu, BOOL *lpfSystem)
void | MNPositionSysMenu (PWND pwnd, PMENU pmenusys)
void | MNFlushDestroyedPopups (PPOPUPMENU ppopupmenu, BOOL fUnlock)
PPOPUPMENU | MNAllocPopup (BOOL fForceAlloc)
VOID | MNFreePopup (PPOPUPMENU ppopupmenu)
BOOL | MNEndMenuStateNotify (PMENUSTATE pMenuState)
void | xxxMNEndMenuState (BOOL fFreePopup)
BOOL | MNCreateAnimationBitmap (PMENUSTATE pMenuState, UINT cx, UINT cy)
void | MNDestroyAnimationBitmap (PMENUSTATE pMenuState)
BOOL | MNSetupAnimationDC (PMENUSTATE pMenuState)
BOOL | xxxUnlockMenuState (PMENUSTATE pMenuState)
PMENUSTATE | xxxMNAllocMenuState (PTHREADINFO ptiCurrent, PTHREADINFO ptiNotify, PPOPUPMENU ppopupmenuRoot)
PMENUSTATE | xxxMNStartMenuState (PWND pwnd, DWORD cmd, LPARAM lParam)
BOOL | xxxMNStartMenu (PPOPUPMENU ppopupmenu, int mn)

## Function Documentation

PPOPUPMENU MNAllocPopup | ( | BOOL | fForceAlloc | ) |

Definition at line 143 of file mnstate.c.

References gpopupMenu, PUDF_POPUPINUSE, SET_PUDF, and TEST_PUDF.

Referenced by xxxMenuWindowProc(), and xxxMNStartMenuState().

    00144 {
    00145     PPOPUPMENU ppm;
    00146     if (!fForceAlloc && !TEST_PUDF(PUDF_POPUPINUSE)) {
    00147         SET_PUDF(PUDF_POPUPINUSE);
    00148
    00149         ppm = &gpopupMenu;
    00150     } else {
    00151         ppm = (PPOPUPMENU)UserAllocPoolWithQuota(sizeof(POPUPMENU), TAG_POPUPMENU);
    00152     }
    00153
    00154     if (ppm) {
    00155         RtlZeroMemory(ppm, sizeof(POPUPMENU));
    00156     }
    00157
    00158     return (ppm);
    00159 }

BOOL MNCreateAnimationBitmap | ( | PMENUSTATE | pMenuState,
|  | UINT | cx,
|  | UINT | cy
| ) |

Definition at line 389 of file mnstate.c.

References BOOL, cy, FALSE, gpDispInfo, tagMENUSTATE::hbmAni, tagDISPLAYINFO::hdcScreen, NULL, and TRUE.

Referenced by xxxMenuWindowProc().

    00390 {
    00391     HBITMAP hbm = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen, cx, cy);
    00392     if (hbm == NULL) {
    00393         RIPMSG0(RIP_WARNING, "MNSetupAnimationBitmap: Failed to create hbmAni");
    00394         return FALSE;
    00395     }
    00396
    00397 #if DBG
    00398     if (pMenuState->hdcAni == NULL) {
    00399         RIPMSG0(RIP_WARNING, "MNCreateAnimationBitmap: hdcAni is NULL");
    00400     }
    00401     if (pMenuState->hbmAni != NULL) {
    00402         RIPMSG0(RIP_WARNING, "MNCreateAnimationBitmap: hbmAni already exists");
    00403     }
    00404 #endif
    00405
    00406     GreSelectBitmap(pMenuState->hdcAni, hbm);
    00407     pMenuState->hbmAni = hbm;
    00408     return TRUE;
    00409 }

void MNDestroyAnimationBitmap | ( | PMENUSTATE | pMenuState | ) |

Definition at line 414 of file mnstate.c.

References tagMENUSTATE::hbmAni, and NULL.

Referenced by MNAnimate(), and xxxMNEndMenuState().

    00415 {
    00416     GreSelectBitmap(pMenuState->hdcAni, GreGetStockObject(PRIV_STOCK_BITMAP));
    00417     UserVerify(GreDeleteObject(pMenuState->hbmAni));
    00418     pMenuState->hbmAni = NULL;
    00419 }

BOOL MNEndMenuStateNotify | ( | PMENUSTATE | pMenuState | ) |

Definition at line 234 of file mnstate.c.

References BOOL, FALSE, GETPTI, NULL, tagMENUSTATE::pGlobalPopupMenu, tagTHREADINFO::pMenuState, tagMENUSTATE::pmnsPrev, tagMENUSTATE::ptiMenuStateOwner, tagPOPUPMENU::spwndNotify, and TRUE.

Referenced by xxxDestroyWindow(), and xxxMNEndMenuState().

    00235 {
    00236     PTHREADINFO ptiNotify;
    00237
    00238     if (pMenuState->pGlobalPopupMenu->spwndNotify != NULL) {
    00239         ptiNotify = GETPTI(pMenuState->pGlobalPopupMenu->spwndNotify);
    00240         if (ptiNotify != pMenuState->ptiMenuStateOwner) {
    00241             /*
    00242              * Later5.0 GerardoB. xxxMNStartMenuState no longer allows this.
    00243              *  This is dead code that I'll remove eventually
    00244              */
    00245             UserAssert(ptiNotify == pMenuState->ptiMenuStateOwner);
    00246
    00247             UserAssert(ptiNotify->pMenuState == pMenuState);
    00248             UserAssert(pMenuState->pmnsPrev == NULL);
    00249             ptiNotify->pMenuState = NULL;
    00250             return TRUE;
    00251         }
    00252     }
    00253
    00254     return FALSE;
    00255 }

void MNFlushDestroyedPopups | ( | PPOPUPMENU | ppopupmenu,
|  | BOOL | fUnlock
| ) |

Definition at line 91 of file mnstate.c.

References FALSE, tagPOPUPMENU::fDelayedFree, tagPOPUPMENU::fDestroyed, IsRootPopupMenu(), MNFreePopup(), NULL, tagPOPUPMENU::ppmDelayedFree, and tagPOPUPMENU::ppopupmenuRoot.

Referenced by MNFreePopup(), and xxxMNLoop().

    00092 {
    00093     PPOPUPMENU ppmDestroyed, ppmFree;
    00094
    00095     UserAssert(IsRootPopupMenu(ppopupmenu));
    00096
    00097     /*
    00098      * Walk ppmDelayedFree
    00099      */
    00100     ppmDestroyed = ppopupmenu;
    00101     while (ppmDestroyed->ppmDelayedFree != NULL) {
    00102         /*
    00103          * If it's marked as destroyed, unlink it and free it
    00104          */
    00105         if (ppmDestroyed->ppmDelayedFree->fDestroyed) {
    00106             ppmFree = ppmDestroyed->ppmDelayedFree;
    00107             ppmDestroyed->ppmDelayedFree = ppmFree->ppmDelayedFree;
    00108             UserAssert(ppmFree != ppmFree->ppopupmenuRoot);
    00109             MNFreePopup(ppmFree);
    00110         } else {
    00111             /*
    00112              * fUnlock is TRUE if the root popup is being destroyed; if
    00113              *  so, reset fDelayedFree and unlink it
    00114              */
    00115             if (fUnlock) {
    00116                 /*
    00117                  * This means that the root popup is going away before
    00118                  *  some of the hierarchical popups have been destroyed.
    00119                  * This can happen if someone destroys one of the menu
    00120                  *  windows breaking the spwndNextPopup chain.
    00121                  */
    00122                 ppmDestroyed->ppmDelayedFree->fDelayedFree = FALSE;
    00123                 /*
    00124                  * Stop here so we can figure how this happened.
    00125                  */
    00126                 UserAssert(ppmDestroyed->ppmDelayedFree->fDelayedFree);
    00127                 ppmDestroyed->ppmDelayedFree = ppmDestroyed->ppmDelayedFree->ppmDelayedFree;
    00128             } else {
    00129                 /*
    00130                  * Not fDestroyed so move to the next one.
    00131                  */
    00132                 ppmDestroyed = ppmDestroyed->ppmDelayedFree;
    00133             } /* fUnlock */
    00134         } /* fDestroyed */
    00135     } /* while ppmDelayedFree */
    00136
    00137 }

VOID MNFreePopup | ( | PPOPUPMENU | ppopupmenu | ) |

Definition at line 165 of file mnstate.c.

References CLEAR_PUDF, DF_MENUINUSE, tagDESKTOP::dwDTFlags, tagPOPUPMENU::fDesktopMenu, tagPOPUPMENU::fFreed, tagPOPUPMENU::fIsMenuBar, FNID_MENU, GETFNID, gpopupMenu, IsRootPopupMenu(), MNFlushDestroyedPopups(), NULL, tagPOPUPMENU::ppopupmenuRoot, PtiCurrent, PUDF_POPUPINUSE, tagPOPUPMENU::spmenu, tagPOPUPMENU::spmenuAlternate, tagPOPUPMENU::spwndActivePopup, tagDESKTOP::spwndMenu, tagPOPUPMENU::spwndNextPopup, tagPOPUPMENU::spwndNotify, tagPOPUPMENU::spwndPopupMenu, tagPOPUPMENU::spwndPrevPopup, TEST_PUDF, TRUE, Unlock, UnlockPopupMenu(), Validateppopupmenu, and VOID().

Referenced by MNFlushDestroyedPopups(), xxxMNDestroyHandler(), xxxMNEndMenuState(), and xxxMNStartMenuState().

    00167 {
    00168
    00169     Validateppopupmenu(ppopupmenu);
    00170
    00171     if (IsRootPopupMenu(ppopupmenu)) {
    00172         MNFlushDestroyedPopups (ppopupmenu, TRUE);
    00173     }
    00174 #if DBG
    00175     /*
    00176      * If this is not a cached menu and it corresponds to a menu window,
    00177      *  then the reference to the popup must be cleared at this point since
    00178      *  we're going to free this popup
    00179      */
    00180     if (ppopupmenu->spwndPopupMenu != NULL) {
    00181         if (!ppopupmenu->fDesktopMenu && !ppopupmenu->fIsMenuBar) {
    00182             UserAssert(GETFNID(ppopupmenu->spwndPopupMenu) == FNID_MENU);
    00183             UserAssert(((PMENUWND)ppopupmenu->spwndPopupMenu)->ppopupmenu == NULL);
    00184         }
    00185     }
    00186 #endif
    00187     Unlock(&ppopupmenu->spwndPopupMenu);
    00188     /*
    00189      * if spwndNextPopup is not NULL, we're breaking the chain and spwndNext won't
    00190      *  get closed. I won't remove the unlock since it has
    00191      *  always been there.
    00192      */
    00193     UserAssert(ppopupmenu->spwndNextPopup == NULL);
    00194     Unlock(&ppopupmenu->spwndNextPopup);
    00195
    00196     Unlock(&ppopupmenu->spwndPrevPopup);
    00197     UnlockPopupMenu(ppopupmenu, &ppopupmenu->spmenu);
    00198     UnlockPopupMenu(ppopupmenu, &ppopupmenu->spmenuAlternate);
    00199     Unlock(&ppopupmenu->spwndNotify);
    00200     Unlock(&ppopupmenu->spwndActivePopup);
    00201
    00202 #if DBG
    00203    if (!ppopupmenu->fDesktopMenu) {
    00204        ppopupmenu->fFreed = TRUE;
    00205    } else {
    00206        PDESKTOP pdesk = PtiCurrent()->rpdesk;
    00207        UserAssert(pdesk->dwDTFlags & DF_MENUINUSE);
    00208        UserAssert(((PMENUWND)pdesk->spwndMenu)->ppopupmenu == ppopupmenu);
    00209    }
    00210 #endif
    00211
    00212     if (ppopupmenu->fDesktopMenu) {
    00213         PtiCurrent()->rpdesk->dwDTFlags &= ~DF_MENUINUSE;
    00214         /* The desktop menu window points to this popup so don't leave bogus stuff in it */
    00215         ppopupmenu->ppopupmenuRoot = NULL;
    00216     } else if (ppopupmenu == &gpopupMenu) {
    00217         UserAssert(TEST_PUDF(PUDF_POPUPINUSE));
    00218         CLEAR_PUDF(PUDF_POPUPINUSE);
    00219     } else {
    00220         UserFreePool(ppopupmenu);
    00221     }
    00222 }

void MNPositionSysMenu | ( | PWND | pwnd,
|  | PMENU | pmenusys
| ) |

Definition at line 25 of file mnstate.c.

References tagMENU::cItems, tagITEM::cxItem, tagITEM::cyItem, FALSE, GetWindowBorders(), Lock, NULL, OffsetRect(), tagMENU::rgItems, tagMENU::spwndNotify, SYSMET, TestMF, TestWF, TRUE, WEFTOOLWINDOW, WFMINIMIZED, tagITEM::xItem, and tagITEM::yItem.

Referenced by xxxMNInvertItem(), xxxMNKeyFilter(), xxxMNStartMenu(), and xxxSetSystemMenu().

    00028 {
    00029     RECT rc;
    00030     PITEM pItem;
    00031
    00032     if (pmenusys == NULL) {
    00033         RIPERR0(ERROR_INVALID_HANDLE,
    00034                 RIP_WARNING,
    00035                 "Invalid menu handle pmenusys (NULL) to MNPositionSysMenu");
    00036
    00037         return;
    00038     }
    00039
    00040     /*
    00041      * Whoever positions the menu becomes the owner
    00042      */
    00043     if (pwnd != pmenusys->spwndNotify) {
    00044         Lock(&pmenusys->spwndNotify, pwnd);
    00045     }
    00046
    00047     /*
    00048      * Setup the SysMenu hit rectangle.
    00049      */
    00050     rc.top = rc.left = 0;
    00051
    00052     if (TestWF(pwnd, WEFTOOLWINDOW)) {
    00053         rc.right = SYSMET(CXSMSIZE);
    00054         rc.bottom = SYSMET(CYSMSIZE);
    00055     } else {
    00056         rc.right = SYSMET(CXSIZE);
    00057         rc.bottom = SYSMET(CYSIZE);
    00058     }
    00059
    00060     if (!TestWF(pwnd, WFMINIMIZED)) {
    00061         int cBorders;
    00062
    00063         cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
    00064         OffsetRect(&rc, cBorders*SYSMET(CXBORDER), cBorders*SYSMET(CYBORDER));
    00065     }
    00066
    00067     /*
    00068      * Offset the System popup menu.
    00069      */
    00070     if (!TestMF(pmenusys, MF_POPUP) && (pmenusys->cItems > 0)) {
    00071         pItem = pmenusys->rgItems;
    00072         if (pItem) {
    00073             pItem->yItem = rc.top;
    00074             pItem->xItem = rc.left;
    00075             pItem->cyItem = rc.bottom - rc.top;
    00076             pItem->cxItem = rc.right - rc.left;
    00077         }
    00078     }
    00079     else
    00080         // BOGUS -- MF_POPUP should never be set on a MENU -- only a MENU ITEM
    00081         UserAssert(FALSE);
    00082 }

BOOL MNSetupAnimationDC | ( | PMENUSTATE | pMenuState | ) |

Definition at line 425 of file mnstate.c.

References BOOL, FALSE, ghMenuFont, gMenuState, gpDispInfo, tagDISPLAYINFO::hdcScreen, NULL, and TRUE.

Referenced by FinalUserInit(), and xxxMNAllocMenuState().

    00426 {
    00427     pMenuState->hdcAni = GreCreateCompatibleDC(gpDispInfo->hdcScreen);
    00428     if (pMenuState->hdcAni == NULL) {
    00429         RIPMSG0(RIP_WARNING, "MNSetupAnimationDC: Failed to create hdcAnimate");
    00430         UserAssert(pMenuState != &gMenuState);
    00431         return FALSE;
    00432     }
    00433     GreSelectFont(pMenuState->hdcAni, ghMenuFont);
    00434     return TRUE;
    00435 }

PMENU xxxGetInitMenuParam | ( | PWND | pwndMenu,
|  | BOOL * | lpfSystem
| ) |

Definition at line 808 of file mnstate.c.

References CheckLock, tagMENU::cItems, FALSE, NULL, tagWND::spmenu, TestWF, TestwndChild, TRUE, WFMINIMIZED, and xxxGetSysMenu().

Referenced by xxxMNStartMenu().

    00809 {
    00810     //
    00811     // Find out what menu we should be sending in WM_INITMENU:
    00812     //      If minimized/child/empty menubar, use system menu
    00813     //
    00814     CheckLock(pwndMenu);
    00815
    00816     if (TestWF(pwndMenu, WFMINIMIZED) ||
    00817         TestwndChild(pwndMenu) ||
    00818         (pwndMenu->spmenu == NULL) ||
    00819         !pwndMenu->spmenu->cItems)
    00820     {
    00821         if (lpfSystem != NULL)
    00822             *lpfSystem = TRUE;
    00823
    00824         return(xxxGetSysMenu(pwndMenu, FALSE));
    00825     }
    00826     else
    00827     {
    00828         if (lpfSystem != NULL)
    00829             *lpfSystem = FALSE;
    00830
    00831         return(pwndMenu->spmenu);
    00832     }
    00833 }

PMENUSTATE xxxMNAllocMenuState | ( | PTHREADINFO | ptiCurrent,
|  | PTHREADINFO | ptiNotify,
|  | PPOPUPMENU | ppopupmenuRoot
| ) |

Definition at line 458 of file mnstate.c.

References BOOL, DBGIncModalMenuCount, gMenuState, IncSFWLockCount(), MENUANIDC, MENUSTATE, MNSetupAnimationDC(), NULL, PBYTE, tagMENUSTATE::pGlobalPopupMenu, tagTHREADINFO::pMenuState, tagMENUSTATE::pmnsPrev, PtiCurrent, tagMENUSTATE::ptiMenuStateOwner, PUDF_MENUSTATEINUSE, tagTHREADINFO::rpdesk, SET_PUDF, TEST_PUDF, TRUE, and xxxMNEndMenuState().

Referenced by xxxMNStartMenuState(), and xxxTrackPopupMenuEx().

    00459 {
    00460     BOOL fAllocate;
    00461     PMENUSTATE pMenuState;
    00462
    00463     UserAssert(PtiCurrent() == ptiCurrent);
    00464     UserAssert(ptiCurrent->rpdesk == ptiNotify->rpdesk);
    00465
    00466     /*
    00467      * If gMenuState is already taken, allocate one.
    00468      */
    00469     fAllocate = TEST_PUDF(PUDF_MENUSTATEINUSE);
    00470     if (fAllocate) {
    00471         pMenuState = (PMENUSTATE)UserAllocPoolWithQuota(sizeof(MENUSTATE), TAG_MENUSTATE);
    00472         if (pMenuState == NULL) {
    00473             return NULL;
    00474         }
    00475     } else {
    00476         /*
    00477          * Use chache global which already has the animation DC setup
    00478          */
    00479         SET_PUDF(PUDF_MENUSTATEINUSE);
    00480         pMenuState = &gMenuState;
    00481         UserAssert(gMenuState.hdcAni != NULL);
    00482         GreSetDCOwner(gMenuState.hdcAni, OBJECT_OWNER_CURRENT);
    00483     }
    00484
    00485     /*
    00486      * Prevent anyone from changing the foreground while this menu is active
    00487      */
    00488     IncSFWLockCount();
    00489     DBGIncModalMenuCount();
    00490
    00491     /*
    00492      * Initialize pMenuState.
    00493      * Animation DC stuff is already setup so don't zero init it.
    00494      */
    00495     RtlZeroMemory(pMenuState, sizeof(MENUSTATE) - sizeof(MENUANIDC));
    00496     pMenuState->pGlobalPopupMenu = ppopupmenuRoot;
    00497     pMenuState->ptiMenuStateOwner = ptiCurrent;
    00498
    00499     /*
    00500      * Save previous state, if any. Then set new state
    00501      */
    00502     pMenuState->pmnsPrev = ptiCurrent->pMenuState;
    00503     ptiCurrent->pMenuState = pMenuState;
    00504
    00505     if (ptiNotify != ptiCurrent) {
    00506         UserAssert(ptiNotify->pMenuState == NULL);
    00507         ptiNotify->pMenuState = pMenuState;
    00508     }
    00509
    00510     /*
    00511      * If the menustate was allocated, set up animation stuff.
    00512      * This is done here because in case of failure, MNEndMenuState
    00513      * will find ptiCurrent->pMenuState properly.
    00514      */
    00515     if (fAllocate) {
    00516         RtlZeroMemory((PBYTE)pMenuState + sizeof(MENUSTATE) -
    00517                 sizeof(MENUANIDC), sizeof(MENUANIDC));
    00518         if (!MNSetupAnimationDC(pMenuState)) {
    00519             xxxMNEndMenuState(TRUE);
    00520             return NULL;
    00521         }
    00522     }
    00523
    00524     return pMenuState;
    00525 }

void xxxMNEndMenuState | ( | BOOL | fFreePopup | ) |

Definition at line 265 of file mnstate.c.

References CLEAR_PUDF, DBGDecModalMenuCount, DecSFWLockCount(), DF_MENUINUSE, tagDESKTOP::dwDTFlags, tagMENUSTATE::dwLockCount, FALSE, tagPOPUPMENU::fDelayedFree, tagPOPUPMENU::fDestroyed, tagPOPUPMENU::fIsMenuBar, tagPOPUPMENU::fIsTrackPopup, tagMENUSTATE::fModelessMenu, GetpMenuState(), GETPTI, gMenuState, tagMENUSTATE::hbmAni, MNDestroyAnimationBitmap(), MNEndMenuStateNotify(), MNFreePopup(), NULL, tagMENUSTATE::pGlobalPopupMenu, tagTHREADINFO::pMenuState, tagMENUSTATE::pmnsPrev, PtiCurrent, tagDESKTOP::PtiList, tagMENUSTATE::ptiMenuStateOwner, PUDF_MENUSTATEINUSE, tagTHREADINFO::rpdesk, tagPOPUPMENU::spwndActivePopup, tagDESKTOP::spwndMenu, TEST_PUDF, tagMENUSTATE::uButtonDownHitArea, tagMENUSTATE::uDraggingHitArea, UnlockMFMWFPWindow(), xxxActivateThisWindow(), and xxxMNSetCapture().

Referenced by xxxCallHandleMenuMessages(), xxxDestroyThreadInfo(), xxxMenuWindowProc(), xxxMNAllocMenuState(), xxxSysCommand(), xxxTrackPopupMenuEx(), and xxxUnlockMenuState().

    00266 {
    00267     PTHREADINFO ptiCurrent = PtiCurrent();
    00268     PMENUSTATE pMenuState;
    00269     pMenuState = ptiCurrent->pMenuState;
    00270     UserAssert(ptiCurrent->pMenuState != NULL);
    00271     UserAssert(ptiCurrent == pMenuState->ptiMenuStateOwner);
    00272
    00273     /*
    00274      * If the menu is locked, someone doesn't want it to go just yet.
    00275      */
    00276     if (pMenuState->dwLockCount != 0) {
    00277         RIPMSG1(RIP_WARNING, "xxxMNEndMenuState Locked:%#p", pMenuState);
    00278         return;
    00279     }
    00280
    00281     MNEndMenuStateNotify(pMenuState);
    00282
    00283     /*
    00284      * pMenuState->pGlobalPopupMenu could be NULL if xxxMNAllocMenuState failed
    00285      */
    00286     if (pMenuState->pGlobalPopupMenu != NULL) {
    00287         if (fFreePopup) {
    00288             UserAssert(pMenuState->pGlobalPopupMenu->fIsMenuBar || pMenuState->pGlobalPopupMenu->fDestroyed);
    00289
    00290             MNFreePopup(pMenuState->pGlobalPopupMenu);
    00291         } else {
    00292             /*
    00293              * This means that we're ending the menustate but the popup menu
    00294              *  window is still around. This can happen when called from
    00295              *  xxxDestroyThreadInfo.
    00296              */
    00297             UserAssert(pMenuState->pGlobalPopupMenu->fIsTrackPopup);
    00298             pMenuState->pGlobalPopupMenu->fDelayedFree = FALSE;
    00299         }
    00300     }
    00301
    00302     /*
    00303      * Unlock MFMWFP windows.
    00304      */
    00305     UnlockMFMWFPWindow(&pMenuState->uButtonDownHitArea);
    00306     UnlockMFMWFPWindow(&pMenuState->uDraggingHitArea);
    00307
    00308     /*
    00309      * Restore the previous state, if any
    00310      */
    00311     ptiCurrent->pMenuState = pMenuState->pmnsPrev;
    00312
    00313    /*
    00314     * This (modal) menu mode is off
    00315     */
    00316    if (!pMenuState->fModelessMenu) {
    00317        DecSFWLockCount();
    00318        DBGDecModalMenuCount();
    00319    }
    00320
    00321     if (pMenuState->hbmAni != NULL) {
    00322         MNDestroyAnimationBitmap(pMenuState);
    00323     }
    00324
    00325     /*
    00326      * Free the menu state
    00327      */
    00328     if (pMenuState == &gMenuState) {
    00329         UserAssert(TEST_PUDF(PUDF_MENUSTATEINUSE));
    00330         CLEAR_PUDF(PUDF_MENUSTATEINUSE);
    00331         GreSetDCOwner(gMenuState.hdcAni, OBJECT_OWNER_PUBLIC);
    00332     } else {
    00333         if (pMenuState->hdcAni != NULL) {
    00334             GreDeleteDC(pMenuState->hdcAni);
    00335         }
    00336         UserFreePool(pMenuState);
    00337     }
    00338
    00339     /*
    00340      * If returning to a modeless menu, make sure have activation
    00341      * If returning to a modal menu, make sure we have capture
    00342      */
    00343    if (ptiCurrent->pMenuState != NULL) {
    00344        if (ptiCurrent->pMenuState->fModelessMenu) {
    00345            xxxActivateThisWindow(ptiCurrent->pMenuState->pGlobalPopupMenu->spwndActivePopup,
    00346                                  0, 0);
    00347        } else {
    00348            xxxMNSetCapture(ptiCurrent->pMenuState->pGlobalPopupMenu);
    00349        }
    00350    }
    00351
    00352 #if DBG
    00353     /*
    00354      * If this thread is not in menu mode anymore, it must not be using
    00355      *  the desktop menu
    00356      */
    00357     if ((ptiCurrent->pMenuState == NULL) && (ptiCurrent->rpdesk->spwndMenu != NULL)) {
    00358         UserAssert(ptiCurrent != GETPTI(ptiCurrent->rpdesk->spwndMenu));
    00359     }
    00360     /*
    00361      * If someone is using the menu window, it must be in menu mode
    00362      */
    00363     if (ptiCurrent->rpdesk->dwDTFlags & DF_MENUINUSE) {
    00364         UserAssert(GetpMenuState(ptiCurrent->rpdesk->spwndMenu) != NULL);
    00365     }
    00366     /*
    00367      * No pti should point to this pMenuState anymore
    00368      * If guModalMenuStateCount is zero, all pMenuState must be NULL or modeless
    00369      */
    00370 {
    00371     PLIST_ENTRY pHead, pEntry;
    00372     PTHREADINFO ptiT;
    00373
    00374     pHead = &(ptiCurrent->rpdesk->PtiList);
    00375     for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) {
    00376        ptiT = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink);
    00377        UserAssert(ptiT->pMenuState != pMenuState);
    00378        if (guModalMenuStateCount == 0) {
    00379            UserAssert(ptiT->pMenuState == NULL || ptiT->pMenuState->fModelessMenu);
    00380        }
    00381    }
    00382 }
    00383 #endif
    00384 }

BOOL xxxMNStartMenu | ( | PPOPUPMENU | ppopupmenu,
|  | int | mn
| ) |

Definition at line 677 of file mnstate.c.

References _GetKeyState(), BOOL, FALSE, tagMENUSTATE::fAutoDismiss, tagMENUSTATE::fButtonAlwaysDown, tagMENUSTATE::fButtonDown, tagPOPUPMENU::fDestroyed, tagMENUSTATE::fDragAndDrop, tagPOPUPMENU::fIsMenuBar, tagPOPUPMENU::fIsSysMenu, tagMENUSTATE::fIsSysMenu, tagPOPUPMENU::fIsTrackPopup, tagMENUSTATE::fMenuStarted, tagMENUSTATE::fModelessMenu, tagPOPUPMENU::fNoNotify, tagMENUSTATE::fNotifyByPos, FWINABLE, GetpMenuState(), HWq, IsRootPopupMenu(), L, LockPopupMenu(), tagMENUSTATE::mnFocus, MNPositionSysMenu(), NT_SUCCESS, NULL, PtoH, tagPOPUPMENU::spmenu, tagPOPUPMENU::spmenuAlternate, tagPOPUPMENU::spwndNotify, TestMF, ThreadLock, ThreadUnlock, TRUE, xxxClientLoadOLE(), xxxGetInitMenuParam(), xxxGetSysMenu(), xxxMNRecomputeBarIfNeeded(), xxxMNReleaseCapture(), xxxMNSetCapture(), xxxSendMessage(), and xxxWindowEvent().

Referenced by xxxMNKeyFilter(), xxxMNLoop(), and xxxTrackPopupMenuEx().

    00680 {
    00681     PWND pwndMenu;
    00682     PMENU pMenu;
    00683     PMENUSTATE pMenuState;
    00684     TL tlpwndMenu;
    00685     TL tlpmenu;
    00686
    00687     UserAssert(IsRootPopupMenu(ppopupmenu));
    00688
    00689     if (ppopupmenu->fDestroyed) {
    00690         return FALSE;
    00691     }
    00692
    00693     pwndMenu = ppopupmenu->spwndNotify;
    00694     ThreadLock(pwndMenu, &tlpwndMenu);
    00695
    00696     pMenuState = GetpMenuState(pwndMenu);
    00697     if (pMenuState == NULL) {
    00698         RIPMSG0(RIP_ERROR, "xxxMNStartMenu: pMenuState == NULL");
    00699         ThreadUnlock(&tlpwndMenu);
    00700         return FALSE;
    00701     }
    00702     pMenuState->mnFocus = mn;
    00703     pMenuState->fMenuStarted = TRUE;
    00704     pMenuState->fButtonDown =
    00705     pMenuState->fButtonAlwaysDown = ((_GetKeyState(VK_LBUTTON) & 0x8000) != 0);
    00706
    00707     xxxMNSetCapture(ppopupmenu);
    00708
    00709     xxxSendMessage(pwndMenu, WM_SETCURSOR, (WPARAM)HWq(pwndMenu),
    00710             MAKELONG(MSGF_MENU, 0));
    00711
    00712     if (ppopupmenu->fIsMenuBar) {
    00713         BOOL    fSystemMenu;
    00714
    00715
    00716         pMenu = xxxGetInitMenuParam(pwndMenu, &fSystemMenu);
    00717
    00718         if (pMenu == NULL) {
    00719             pMenuState->fMenuStarted = FALSE;
    00720             xxxMNReleaseCapture();
    00721             ThreadUnlock(&tlpwndMenu);
    00722             return(FALSE);
    00723         }
    00724
    00725         LockPopupMenu(ppopupmenu, &ppopupmenu->spmenu, pMenu);
    00726
    00727         ppopupmenu->fIsSysMenu = (fSystemMenu != 0);
    00728         if (!fSystemMenu) {
    00729             pMenu = xxxGetSysMenu(pwndMenu, FALSE);
    00730             LockPopupMenu(ppopupmenu, &ppopupmenu->spmenuAlternate, pMenu);
    00731         }
    00732     }
    00733
    00734     pMenuState->fIsSysMenu = (ppopupmenu->fIsSysMenu != 0);
    00735
    00736     if (!ppopupmenu->fNoNotify) {
    00737
    00738         if (ppopupmenu->fIsTrackPopup && ppopupmenu->fIsSysMenu) {
    00739             pMenu = xxxGetInitMenuParam(pwndMenu, NULL);
    00740         } else {
    00741             pMenu = ppopupmenu->spmenu;
    00742         }
    00743
    00744         xxxSendMessage(pwndMenu, WM_INITMENU, (WPARAM)PtoH(pMenu), 0L);
    00745     }
    00746
    00747     if (!ppopupmenu->fIsTrackPopup) {
    00748         if (ppopupmenu->fIsSysMenu) {
    00749             MNPositionSysMenu(pwndMenu, ppopupmenu->spmenu);
    00750         } else if (ppopupmenu->fIsMenuBar) {
    00751             ThreadLock(ppopupmenu->spmenu, &tlpmenu);
    00752             xxxMNRecomputeBarIfNeeded(pwndMenu, ppopupmenu->spmenu);
    00753             ThreadUnlock(&tlpmenu);
    00754             MNPositionSysMenu(pwndMenu, ppopupmenu->spmenuAlternate);
    00755         }
    00756     }
    00757
    00758     /*
    00759      * If returning TRUE, set menu style in pMenuState
    00760      */
    00761     if (!ppopupmenu->fDestroyed) {
    00762         if (TestMF(ppopupmenu->spmenu, MNS_MODELESS)) {
    00763             pMenuState->fModelessMenu = TRUE;
    00764         }
    00765
    00766         if (TestMF(ppopupmenu->spmenu, MNS_DRAGDROP)) {
    00767             if (NT_SUCCESS(xxxClientLoadOLE())) {
    00768                 pMenuState->fDragAndDrop = TRUE;
    00769             }
    00770         }
    00771
    00772         if (TestMF(ppopupmenu->spmenu, MNS_AUTODISMISS)) {
    00773             pMenuState->fAutoDismiss = TRUE;
    00774         }
    00775
    00776         if (TestMF(ppopupmenu->spmenu, MNS_NOTIFYBYPOS)) {
    00777             pMenuState->fNotifyByPos = TRUE;
    00778         }
    00779
    00780     }
    00781
    00782     /*
    00783      * Bogus!  We don't always know that this is the system menu.  We
    00784      * will frequently pass on an OBJID_MENU even when you hit Alt+Space.
    00785      *
    00786      * Hence, MNSwitchToAlternate will send a EVENT_SYSTEM_MENUEND for the
    00787      * menu bar and an EVENT_SYSTEM_MENUSTART for the sysmenu when we "switch".
    00788      */
    00789     if (FWINABLE()) {
    00790         xxxWindowEvent(EVENT_SYSTEM_MENUSTART, pwndMenu,
    00791                 (ppopupmenu->fIsSysMenu ? OBJID_SYSMENU : (ppopupmenu->fIsMenuBar ? OBJID_MENU : OBJID_WINDOW)),
    00792                 INDEXID_CONTAINER, 0);
    00793     }
    00794
    00795     ThreadUnlock(&tlpwndMenu);
    00796
    00797     return !ppopupmenu->fDestroyed;
    00798 }

PMENUSTATE xxxMNStartMenuState | ( | PWND | pwnd,
|  | DWORD | cmd,
|  | LPARAM | lParam
| ) |

Definition at line 540 of file mnstate.c.

References _PostMessage(), CheckLock, FALSE, tagPOPUPMENU::fHasMenuBar, tagPOPUPMENU::fIsMenuBar, tagPOPUPMENU::fRtoL, GETPTI, L, Lock, MFMWFP_NOITEM, MFRTL, MNAllocPopup(), MNFreePopup(), NULL, tagTHREADINFO::pMenuState, tagPOPUPMENU::posSelectedItem, tagPOPUPMENU::ppopupmenuRoot, PtiCurrent, tagWND::spmenu, tagPOPUPMENU::spwndNotify, tagWND::spwndParent, tagPOPUPMENU::spwndPopupMenu, TestMF, TestWF, TestwndChild, ThreadLockAlways, ThreadUnlock, TRUE, WEFRTLREADING, WFSYSMENU, xxxMNAllocMenuState(), and xxxSendMessage().

Referenced by xxxSysCommand().

    00541 {
    00542     PPOPUPMENU ppopupmenu;
    00543     PTHREADINFO ptiCurrent, ptiNotify;
    00544     PMENUSTATE pMenuState;
    00545     TL tlpwnd;
    00546     PWND pwndT;
    00547
    00548     CheckLock(pwnd);
    00549
    00550     /*
    00551      * Bail if the current thread is already in menu mode
    00552      */
    00553     ptiCurrent = PtiCurrent();
    00554     if (ptiCurrent->pMenuState != NULL) {
    00555         return NULL;
    00556     }
    00557
    00558     /*
    00559      * If pwnd is not owned by ptiCurrent, the _PostMessage call below might
    00560      *  send us in a loop
    00561      */
    00562     UserAssert(ptiCurrent == GETPTI(pwnd));
    00563
    00564     /*
    00565      * If this is not a child window, use the active window on its queue
    00566      */
    00567     if (!TestwndChild(pwnd)) {
    00568         pwnd = GETPTI(pwnd)->pq->spwndActive;
    00569     } else {
    00570         /*
    00571          * Search up the parents for a window with a System Menu.
    00572          */
    00573         while (TestwndChild(pwnd)) {
    00574             if (TestWF(pwnd, WFSYSMENU)) {
    00575                 break;
    00576             }
    00577             pwnd = pwnd->spwndParent;
    00578         }
    00579     }
    00580
    00581     if (pwnd == NULL) {
    00582         return NULL;
    00583     }
    00584
    00585     if (!TestwndChild(pwnd) && (pwnd->spmenu != NULL)) {
    00586         goto hasmenu;
    00587     }
    00588
    00589     if (!TestWF(pwnd, WFSYSMENU)) {
    00590         return NULL;
    00591     }
    00592
    00593 hasmenu:
    00594
    00595     /*
    00596      * If the owner/notification window was created by another thread,
    00597      *  make sure that it's not in menu mode already
    00598      * This can happen if PtiCurrent() is attached to other threads, one of
    00599      *  which created pwnd.
    00600      */
    00601     ptiNotify = GETPTI(pwnd);
    00602     if (ptiNotify->pMenuState != NULL) {
    00603         return NULL;
    00604     }
    00605
    00606     /*
    00607      * If the notification window is owned by another thread,
    00608      *   then the menu loop wouldn't get any keyboard or mouse
    00609      *   messages because we set capture to the notification window.
    00610      * So we pass the WM_SYSCOMMAND to that thread and bail
    00611      */
    00612     if (ptiNotify != ptiCurrent) {
    00613         RIPMSG2(RIP_WARNING, "Passing WM_SYSCOMMAND SC_*MENU from thread %#p to %#p", ptiCurrent, ptiNotify);
    00614         _PostMessage(pwnd, WM_SYSCOMMAND, cmd, lParam);
    00615         return NULL;
    00616     }
    00617
    00618     /*
    00619      * Allocate ppoupmenu and pMenuState
    00620      */
    00621     ppopupmenu = MNAllocPopup(FALSE);
    00622     if (ppopupmenu == NULL) {
    00623         return NULL;
    00624     }
    00625
    00626     pMenuState = xxxMNAllocMenuState(ptiCurrent, ptiNotify, ppopupmenu);
    00627     if (pMenuState == NULL) {
    00628         MNFreePopup(ppopupmenu);
    00629         return NULL;
    00630     }
    00631
    00632     ppopupmenu->fIsMenuBar = TRUE;
    00633     ppopupmenu->fHasMenuBar = TRUE;
    00634     Lock(&(ppopupmenu->spwndNotify), pwnd);
    00635     ppopupmenu->posSelectedItem = MFMWFP_NOITEM;
    00636     Lock(&(ppopupmenu->spwndPopupMenu), pwnd);
    00637     ppopupmenu->ppopupmenuRoot = ppopupmenu;
    00638
    00639     pwndT = pwnd;
    00640     while( TestwndChild(pwndT) )
    00641         pwndT = pwndT->spwndParent;
    00642
    00643     if (pwndT->spmenu)
    00644         ppopupmenu->fRtoL = TestMF(pwndT->spmenu, MFRTL) ?TRUE:FALSE;
    00645     else {
    00646         //
    00647         // no way to know, no menu, but there is a system menu. Thus arrow
    00648         // keys are really not important. however lets take the next best
    00649         // thing just to be safe
    00650         //
    00651         ppopupmenu->fRtoL = TestWF(pwnd, WEFRTLREADING) ?TRUE :FALSE;
    00652     }
    00653     /*
    00654      * Notify the app we are entering menu mode.  wParam is always 0 since this
    00655      * procedure will only be called for menu bar menus not TrackPopupMenu
    00656      * menus.
    00657      */
    00658     ThreadLockAlways(pwnd, &tlpwnd);
    00659     xxxSendMessage(pwnd, WM_ENTERMENULOOP, 0, 0L);
    00660     ThreadUnlock(&tlpwnd);
    00661
    00662     return pMenuState;
    00663 }

BOOL xxxUnlockMenuState | ( | PMENUSTATE | pMenuState | ) |

Definition at line 441 of file mnstate.c.

References BOOL, tagMENUSTATE::dwLockCount, ExitMenuLoop(), FALSE, tagMENUSTATE::pGlobalPopupMenu, TRUE, and xxxMNEndMenuState().

Referenced by xxxMenuWindowProc(), xxxMNDragLeave(), and xxxMNDragOver().

    00442 {
    00443     UserAssert(pMenuState->dwLockCount != 0);
    00444     (pMenuState->dwLockCount)--;
    00445     if ((pMenuState->dwLockCount == 0) && ExitMenuLoop(pMenuState, pMenuState->pGlobalPopupMenu)) {
    00446         xxxMNEndMenuState(TRUE);
    00447         return TRUE;
    00448     }
    00449     return FALSE;
    00450 }