test: menudd.c File Reference

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

# menudd.c File Reference

`#include "precomp.h"`
`#include "callback.h"`

Go to the source code of this file.

## Functions

NTSTATUS | xxxClientLoadOLE (void)
NTSTATUS | xxxClientRegisterDragDrop (HWND hwnd)
NTSTATUS | xxxClientRevokeDragDrop (HWND hwnd)
void | xxxMNSetGapState (ULONG_PTR uHitArea, UINT uIndex, UINT uFlags, BOOL fSet)
BOOL | xxxMNDragOver (POINT *ppt, PMNDRAGOVERINFO pmndoi)
BOOL | xxxMNDragLeave (VOID)
void | xxxMNUpdateDraggingInfo (PMENUSTATE pMenuState, ULONG_PTR uHitArea, UINT uIndex)

## Function Documentation

NTSTATUS xxxClientLoadOLE | ( | void |  | ) |

Definition at line 24 of file menudd.c.

References NT_SUCCESS, NTSTATUS(), NULL, PpiCurrent, Status, and xxxUserModeCallback().

Referenced by xxxMNStartMenu().

    00025 {
    00026     NTSTATUS Status;
    00027     PPROCESSINFO ppiCurrent = PpiCurrent();
    00028
    00029     if (ppiCurrent->W32PF_Flags & W32PF_OLELOADED) {
    00030         return STATUS_SUCCESS;
    00031     }
    00032
    00033     Status = xxxUserModeCallback(FI_CLIENTLOADOLE, NULL, 0, NULL, 0);
    00034     if (NT_SUCCESS(Status)) {
    00035         ppiCurrent->W32PF_Flags |= W32PF_OLELOADED;
    00036     }
    00037     return Status;
    00038 }

NTSTATUS xxxClientRegisterDragDrop | ( | HWND | hwnd | ) |

Definition at line 44 of file menudd.c.

References NTSTATUS(), NULL, and xxxUserModeCallback().

Referenced by xxxMNOpenHierarchy(), and xxxTrackPopupMenuEx().

    00045 {
    00046     return xxxUserModeCallback(FI_CLIENTREGISTERDRAGDROP, &hwnd, sizeof(&hwnd), NULL, 0);
    00047 }

NTSTATUS xxxClientRevokeDragDrop | ( | HWND | hwnd | ) |

Definition at line 53 of file menudd.c.

References NTSTATUS(), NULL, and xxxUserModeCallback().

Referenced by xxxMenuWindowProc(), and xxxMNCloseHierarchy().

    00054 {
    00055     return xxxUserModeCallback(FI_CLIENTREVOKEDRAGDROP, &hwnd, sizeof(&hwnd), NULL, 0);
    00056
    00057 }

BOOL xxxMNDragLeave | ( | VOID |  | ) |

Definition at line 237 of file menudd.c.

References BOOL, FALSE, tagMENUSTATE::fInDoDragDrop, LockMenuState(), MFMWFP_NOITEM, NULL, PtiCurrent, TRUE, tagMENUSTATE::uDraggingFlags, tagMENUSTATE::uDraggingHitArea, tagMENUSTATE::uDraggingIndex, UnlockMFMWFPWindow(), xxxMNSetGapState(), and xxxUnlockMenuState().

Referenced by NtUserMNDragLeave().

    00238 {
    00239     PMENUSTATE pMenuState;
    00240
    00241     pMenuState = PtiCurrent()->pMenuState;
    00242     if (pMenuState == NULL) {
    00243         RIPMSG0(RIP_WARNING, "xxxMNDragLeave: Not in menu mode");
    00244         return FALSE;
    00245     }
    00246
    00247     LockMenuState(pMenuState);
    00248
    00249     /*
    00250      * Clean up any present insertion bar state
    00251      */
    00252     xxxMNSetGapState(pMenuState->uDraggingHitArea,
    00253                   pMenuState->uDraggingIndex,
    00254                   pMenuState->uDraggingFlags,
    00255                   FALSE);
    00256
    00257     /*
    00258      * Forget the last dragging area
    00259      */
    00260     UnlockMFMWFPWindow(&pMenuState->uDraggingHitArea);
    00261     pMenuState->uDraggingIndex = MFMWFP_NOITEM;
    00262     pMenuState->uDraggingFlags = 0;
    00263
    00264
    00265     /*
    00266      * The DoDragDrop loop has left our window.
    00267      */
    00268     pMenuState->fInDoDragDrop = FALSE;
    00269
    00270     xxxUnlockMenuState(pMenuState);
    00271
    00272     return TRUE;
    00273 }

BOOL xxxMNDragOver | ( | POINT * | ppt,
|  | PMNDRAGOVERINFO | pmndoi
| ) |

Definition at line 156 of file menudd.c.

References BOOL, tagMNDRAGOVERINFO::dwFlags, FALSE, tagMENUSTATE::fDragAndDrop, tagMENUSTATE::fInDoDragDrop, GetMenuStateWindow(), tagMNDRAGOVERINFO::hmenu, tagMNDRAGOVERINFO::hwndNotify, LockMenuState(), MFMWFP_NOITEM, MFMWFP_OFFMENU, NULL, PMNDRAGOVERINFO, PtiCurrent, PtoH, tagPOPUPMENU::spmenu, tagPOPUPMENU::spwndNotify, ThreadLockAlways, ThreadUnlock, TRUE, tagMENUSTATE::uDraggingFlags, tagMENUSTATE::uDraggingHitArea, tagMENUSTATE::uDraggingIndex, tagMNDRAGOVERINFO::uItemIndex, xxxCallHandleMenuMessages(), and xxxUnlockMenuState().

Referenced by NtUserMNDragOver().

    00157 {
    00158     BOOL fRet;
    00159     PMENUSTATE pMenuState;
    00160     PWND pwnd;
    00161     PPOPUPMENU ppopup;
    00162     TL tlpwnd;
    00163
    00164     /*
    00165      * OLE always calls us in context (proxy/marshall stuff). So the
    00166      *  current thread must be in menu mode
    00167      */
    00168     pMenuState = PtiCurrent()->pMenuState;
    00169     if (pMenuState == NULL) {
    00170         RIPMSG0(RIP_WARNING, "xxxMNDragOver: Not in menu mode");
    00171         return FALSE;
    00172     }
    00173
    00174     /*
    00175      * This must be a drag and drop menu
    00176      */
    00177     UserAssert(pMenuState->fDragAndDrop);
    00178
    00179     /*
    00180      * We might have not initiated this DoDragDrop so make sure
    00181      *  the internal flag is set.
    00182      */
    00183     pMenuState->fInDoDragDrop = TRUE;
    00184
    00185     /*
    00186      * Get a window to call xxxCallHandleMenuMessages
    00187      */
    00188     pwnd = GetMenuStateWindow(pMenuState);
    00189     if (pwnd == NULL) {
    00190         RIPMSG0(RIP_WARNING, "xxxMNDragOver: Failed to get MenuStateWindow");
    00191         return FALSE;
    00192     }
    00193
    00194     /*
    00195      * We need this after calling back, so lock it
    00196      */
    00197     LockMenuState(pMenuState);
    00198
    00199     /*
    00200      * Update the selection and the dragging info
    00201      * Use WM_NCMOUSEMOVE because the point is in screen coordinates already.
    00202      */
    00203     ThreadLockAlways(pwnd, &tlpwnd);
    00204     xxxCallHandleMenuMessages(pMenuState, pwnd, WM_NCMOUSEMOVE, 0, MAKELONG(ppt->x, ppt->y));
    00205     ThreadUnlock(&tlpwnd);
    00206
    00207     /*
    00208      * If we're on a popup, propagate the hit test info
    00209      */
    00210     if (pMenuState->uDraggingHitArea != MFMWFP_OFFMENU) {
    00211         ppopup = ((PMENUWND)pMenuState->uDraggingHitArea)->ppopupmenu;
    00212         pmndoi->hmenu = PtoH(ppopup->spmenu);
    00213         pmndoi->uItemIndex = pMenuState->uDraggingIndex;
    00214         pmndoi->hwndNotify = PtoH(ppopup->spwndNotify);
    00215         pmndoi->dwFlags = pMenuState->uDraggingFlags;
    00216         /*
    00217          * Bottom gap of item N corresponds to N+1 gap
    00218          */
    00219         if (pmndoi->dwFlags & MNGOF_BOTTOMGAP) {
    00220             UserAssert(pmndoi->uItemIndex != MFMWFP_NOITEM);
    00221             (pmndoi->uItemIndex)++;
    00222         }
    00223         fRet = TRUE;
    00224     } else {
    00225         fRet = FALSE;
    00226     }
    00227
    00228     xxxUnlockMenuState(pMenuState);
    00229     return fRet;;
    00230
    00231 }

void xxxMNSetGapState | ( | ULONG_PTR | uHitArea,
|  | UINT | uIndex,
|  | UINT | uFlags,
|  | BOOL | fSet
| ) |

Definition at line 63 of file menudd.c.

References ClearMFS, tagITEM::cxItem, tagITEM::cyItem, IsMFMWFPWindow(), MNGetpItem(), MNGetToppItem(), NULL, SetMFS, tagPOPUPMENU::spmenu, SYSMET, ThreadLockAlways, ThreadUnlock, TRUE, tagITEM::xItem, xxxInvalidateRect(), and tagITEM::yItem.

Referenced by xxxInsertMenuItem(), xxxMNDragLeave(), and xxxMNUpdateDraggingInfo().

    00064 {
    00065     int yTop;
    00066     PITEM pItem, pItemGap;
    00067     PPOPUPMENU ppopup;
    00068     RECT rc;
    00069     TL tlHitArea;
    00070
    00071     /*
    00072      * Bail if there is nothing to do.
    00073      */
    00074     if (!(uFlags & MNGOF_GAP) || !IsMFMWFPWindow(uHitArea)) {
    00075         return;
    00076     }
    00077
    00078     ppopup = ((PMENUWND)uHitArea)->ppopupmenu;
    00079     pItem = MNGetpItem(ppopup, uIndex);
    00080
    00081     /*
    00082      * The menu window might be destroyed by now so pItem could be NULL.
    00083      */
    00084     if (pItem == NULL) {
    00085         return;
    00086     }
    00087
    00088     /*
    00089      * Mark the item and set the rectangle we need to redraw.
    00090      * Drawing/erasing the insertion bar unhilites/hiltes the
    00091      *  item, so pItem needs to be redrawn completely. In additon,
    00092      *  we need to draw the insertion bar in the next/previous item.
    00093      */
    00094     rc.left = pItem->xItem;
    00095     rc.right = pItem->xItem + pItem->cxItem;
    00096     rc.top = pItem->yItem;
    00097     rc.bottom = pItem->yItem + pItem->cyItem;
    00098
    00099     if (uFlags & MNGOF_TOPGAP) {
    00100         pItemGap = MNGetpItem(ppopup, uIndex - 1);
    00101         if (fSet) {
    00102             SetMFS(pItem, MFS_TOPGAPDROP);
    00103             if (pItemGap != NULL) {
    00104                 SetMFS(pItemGap, MFS_BOTTOMGAPDROP);
    00105             }
    00106         } else {
    00107             ClearMFS(pItem, MFS_TOPGAPDROP);
    00108             if (pItemGap != NULL) {
    00109                 ClearMFS(pItemGap, MFS_BOTTOMGAPDROP);
    00110             }
    00111         }
    00112         if (pItemGap != NULL) {
    00113             rc.top -= SYSMET(CYDRAG);
    00114         }
    00115     } else {
    00116         pItemGap = MNGetpItem(ppopup, uIndex + 1);
    00117         if (fSet) {
    00118             SetMFS(pItem, MFS_BOTTOMGAPDROP);
    00119             if (pItemGap != NULL) {
    00120                 SetMFS(pItemGap, MFS_TOPGAPDROP);
    00121             }
    00122         } else {
    00123             ClearMFS(pItem, MFS_BOTTOMGAPDROP);
    00124             if (pItemGap != NULL) {
    00125                 ClearMFS(pItemGap, MFS_TOPGAPDROP);
    00126             }
    00127         }
    00128         if (pItemGap != NULL) {
    00129             rc.bottom += SYSMET(CYDRAG);
    00130         }
    00131     }
    00132
    00133     /*
    00134      * Adjust to "menu" coordinates (for scrollable menus)
    00135      */
    00136     yTop = MNGetToppItem(ppopup->spmenu)->yItem;
    00137     rc.top -= yTop;
    00138     rc.bottom -= yTop;
    00139
    00140     /*
    00141      * Invalidate this rect to repaint it later
    00142      */
    00143     ThreadLockAlways((PWND)uHitArea, &tlHitArea);
    00144     xxxInvalidateRect((PWND)uHitArea, &rc, TRUE);
    00145     ThreadUnlock(&tlHitArea);
    00146 }

void xxxMNUpdateDraggingInfo | ( | PMENUSTATE | pMenuState,
|  | ULONG_PTR | uHitArea,
|  | UINT | uIndex
| ) |

Definition at line 279 of file menudd.c.

References BOOL, tagITEM::cyItem, FALSE, IsMFMWFPWindow(), LockMFMWFPWindow(), MFMWFP_NOITEM, MFMWFP_OFFMENU, MNGetpItem(), MNGetToppItem(), NULL, tagMENUSTATE::ptMouseLast, tagPOPUPMENU::spmenu, SYSMET, ThreadLock, ThreadUnlock, TRUE, tagMENUSTATE::uDraggingFlags, tagMENUSTATE::uDraggingHitArea, tagMENUSTATE::uDraggingIndex, UINT, xxxMNSetGapState(), and tagITEM::yItem.

Referenced by xxxMNMouseMove().

    00280 {
    00281     BOOL fCross;
    00282     int y, iIndexDelta;
    00283     PITEM pItem;
    00284     PPOPUPMENU ppopup;
    00285     TL tlLastHitArea;
    00286     ULONG_PTR uLastHitArea;
    00287     UINT uLastIndex, uLastFlags;
    00288
    00289     /*
    00290      * Remember current dragging area so we can detected when
    00291      *  crossing item/gap boundries.
    00292      */
    00293     UserAssert((pMenuState->uDraggingHitArea == 0) || IsMFMWFPWindow(pMenuState->uDraggingHitArea));
    00294     ThreadLock((PWND)pMenuState->uDraggingHitArea, &tlLastHitArea);
    00295     uLastHitArea = pMenuState->uDraggingHitArea;
    00296     uLastIndex = pMenuState->uDraggingIndex;
    00297     uLastFlags = pMenuState->uDraggingFlags & MNGOF_GAP;
    00298
    00299     /*
    00300      * Store new dragging area.
    00301      */
    00302     LockMFMWFPWindow(&pMenuState->uDraggingHitArea, uHitArea);
    00303     pMenuState->uDraggingIndex = uIndex;
    00304
    00305     /*
    00306      * If we're not on a popup, done.
    00307      */
    00308     if (!IsMFMWFPWindow(pMenuState->uDraggingHitArea)) {
    00309         pMenuState->uDraggingHitArea = MFMWFP_OFFMENU;
    00310         pMenuState->uDraggingIndex = MFMWFP_NOITEM;
    00311         ThreadUnlock(&tlLastHitArea);
    00312         return;
    00313     }
    00314
    00315     /*
    00316      * Get the popup and item we're on
    00317      */
    00318     ppopup = ((PMENUWND)pMenuState->uDraggingHitArea)->ppopupmenu;
    00319     pItem = MNGetpItem(ppopup, pMenuState->uDraggingIndex);
    00320
    00321     /*
    00322      * Find out if we're on the gap, that is, the "virtual" space
    00323      *  between items. Some apps want to distinguish between a drop
    00324      *  ON the item and a drop BEFORE/AFTER the item; there is no
    00325      *  actual space between items so we define a virtual gap
    00326      *
    00327      */
    00328     pMenuState->uDraggingFlags = 0;
    00329     if (pItem != NULL) {
    00330         /*
    00331          * Map the point to client coordinates and then to "menu"
    00332          *  coordinates (to take care of scrollable menus)
    00333          */
    00334         y = pMenuState->ptMouseLast.y;
    00335         y -= ((PWND)pMenuState->uDraggingHitArea)->rcClient.top;
    00336         y += MNGetToppItem(ppopup->spmenu)->yItem;
    00337 #if DBG
    00338         if ((y < (int)pItem->yItem)
    00339                 || (y > (int)(pItem->yItem + pItem->cyItem))) {
    00340             RIPMSG4(RIP_ERROR, "xxxMNUpdateDraggingInfo: y Point not in selected item. "
    00341                                "pwnd:%#lx ppopup:%#lx Index:%#lx pItem:%#lx",
    00342                                pMenuState->uDraggingHitArea, ppopup, pMenuState->uDraggingIndex, pItem);
    00343         }
    00344 #endif
    00345
    00346         /*
    00347          * Top/bottom gap check
    00348          */
    00349         if (y <= (int)(pItem->yItem + SYSMET(CYDRAG))) {
    00350             pMenuState->uDraggingFlags = MNGOF_TOPGAP;
    00351         } else if (y >= (int)(pItem->yItem + pItem->cyItem - SYSMET(CYDRAG))) {
    00352             pMenuState->uDraggingFlags = MNGOF_BOTTOMGAP;
    00353         }
    00354     }
    00355
    00356     /*
    00357      * Have we crossed an item/gap boundary?
    00358      * We don't cross a boundary when we move from the bottom
    00359      *  of an item to the top of the next, or, from the top
    00360      *  of an item to the bottom of the previous.
    00361      *  (Item N is on top of and previous to item N+1).
    00362      */
    00363     fCross = (uLastHitArea != pMenuState->uDraggingHitArea);
    00364     if (!fCross) {
    00365         iIndexDelta = (int)pMenuState->uDraggingIndex - (int)uLastIndex;
    00366         switch (iIndexDelta) {
    00367             case 0:
    00368                 /*
    00369                  * We're on the same item.
    00370                  */
    00371                 fCross = (uLastFlags != pMenuState->uDraggingFlags);
    00372                 break;
    00373
    00374             case 1:
    00375                 /*
    00376                  * We've moved to the next item
    00377                  */
    00378                 fCross = !((pMenuState->uDraggingFlags == MNGOF_TOPGAP)
    00379                           && (uLastFlags == MNGOF_BOTTOMGAP));
    00380                 break;
    00381
    00382             case -1:
    00383                 /*
    00384                  * We've moved to the previous item
    00385                  */
    00386                 fCross = !((pMenuState->uDraggingFlags == MNGOF_BOTTOMGAP)
    00387                           && (uLastFlags == MNGOF_TOPGAP));
    00388                 break;
    00389
    00390             default:
    00391                 /*
    00392                  * We've skipped more than one item.
    00393                  */
    00394                 fCross = TRUE;
    00395         }
    00396     }
    00397
    00398     if (fCross) {
    00399         pMenuState->uDraggingFlags |= MNGOF_CROSSBOUNDARY;
    00400
    00401         /*
    00402          * Update the insertion bar state.
    00403          */
    00404         xxxMNSetGapState(uLastHitArea, uLastIndex, uLastFlags, FALSE);
    00405         xxxMNSetGapState(pMenuState->uDraggingHitArea,
    00406                       pMenuState->uDraggingIndex,
    00407                       pMenuState->uDraggingFlags,
    00408                       TRUE);
    00409     }
    00410
    00411     ThreadUnlock(&tlLastHitArea);
    00412 }