00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
#include "precomp.h"
00014
#pragma hdrstop
00015
00016
00017
00018
00019
00020
00021
#if DBG
00022
UINT DBGMNGetpItemIndex(
PMENU pmenu,
PITEM pitem)
00023 {
00024
UINT uiPos;
00025 UserAssert((ULONG_PTR)pitem >= (ULONG_PTR)pmenu->
rgItems);
00026 uiPos =
_MNGetpItemIndex(pmenu, pitem);
00027 UserAssert(uiPos < pmenu->cItems);
00028
return uiPos;
00029 }
00030
#endif
00031
00032
00033
00034
00035
00036 void xxxMNDismiss (
PMENUSTATE pMenuState)
00037 {
00038
xxxMNCancel(pMenuState, 0, 0, 0);
00039 }
00040
00041
00042
00043
00044
00045
00046
00047 BOOL MNFadeSelection(
PMENU pmenu,
PITEM pitem)
00048 {
00049
PWND pwnd;
00050 HDC hdc;
00051 RECT rc;
00052
PPOPUPMENU ppopup;
00053
00054
if (!
TestALPHA(SELECTIONFADE))
00055
return FALSE;
00056
00057
00058
00059
00060
if ((ppopup =
MNGetPopupFromMenu(pmenu,
NULL)) ==
NULL)
00061
return FALSE;
00062
00063
if ((pwnd = ppopup->
spwndPopupMenu) ==
NULL)
00064
return FALSE;
00065
00066 rc.left = pwnd->
rcClient.left + pitem->
xItem;
00067 rc.top = pwnd->
rcClient.top + pitem->
yItem;
00068 rc.right = rc.left + pitem->
cxItem;
00069 rc.bottom = rc.top + pitem->
cyItem;
00070
00071
00072
00073
00074
if ((hdc =
CreateFade(
NULL, &rc,
CMS_SELECTIONFADE, 0)) ==
NULL)
00075
return FALSE;
00076
00077
00078
00079
00080
00081
00082
00083 GreBitBlt(hdc, 0, 0, pitem->
cxItem, pitem->
cyItem,
gpDispInfo->
hdcScreen,
00084 rc.left, rc.top, SRCCOPY, 0);
00085
00086
ShowFade();
00087
00088
return TRUE;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 void xxxMNDismissWithNotify (
PMENUSTATE pMenuState,
PMENU pmenu,
PITEM pitem,
00099 UINT uPos, LPARAM lParam)
00100 {
00101
UINT uMsg;
00102
UINT uCmd;
00103
00104
if (pMenuState->
pGlobalPopupMenu->
fIsSysMenu) {
00105 uMsg = WM_SYSCOMMAND;
00106 uCmd = pitem->
wID;
00107
00108 }
else if (pMenuState->
fNotifyByPos) {
00109 uMsg = WM_MENUCOMMAND;
00110 uCmd = uPos;
00111 lParam = (LPARAM)
PtoHq(pmenu);
00112 }
else {
00113 uMsg = WM_COMMAND;
00114 uCmd = pitem->
wID;
00115 lParam = 0;
00116 }
00117
00118
00119
00120
00121
if (
MNFadeSelection(pmenu, pitem)) {
00122
StartFade();
00123 }
00124
00125
00126
00127
00128
xxxMNCancel(pMenuState, uMsg, uCmd, lParam);
00129 }
00130
00131
00132
00133
00134
00135
00136 PITEM MNGetpItem(
PPOPUPMENU ppopup, UINT uIndex)
00137 {
00138
if ((ppopup ==
NULL)
00139 || (uIndex >= ppopup->
spmenu->
cItems)) {
00140
00141
return NULL;
00142 }
00143
00144
return ppopup->
spmenu->
rgItems + uIndex;
00145 }
00146
00147
00148
00149
00150
00151
00152 void xxxMNSetCapture (
PPOPUPMENU ppopup)
00153 {
00154
PTHREADINFO ptiCurrent =
PtiCurrent();
00155
00156
00157
00158
00159
00160
xxxCapture(ptiCurrent, ppopup->
spwndNotify,
SCREEN_CAPTURE);
00161 UserAssert (ptiCurrent->
pq->
spwndCapture == ppopup->
spwndNotify);
00162 ptiCurrent->
pq->
QF_flags |=
QF_CAPTURELOCKED;
00163 ptiCurrent->
pMenuState->
fSetCapture =
TRUE;
00164
#if DBG
00165
00166
00167
00168
00169
00170
if (ptiCurrent->
pq !=
gpqForeground) {
00171 RIPMSG0(RIP_WARNING,
"xxxMNSetCapture: Menu mode is not in foreground queue");
00172 }
00173
#endif
00174
}
00175
00176
00177
00178
00179
00180
00181 void xxxMNReleaseCapture (
void)
00182 {
00183
PTHREADINFO ptiCurrent =
PtiCurrent();
00184
00185
00186
00187
00188
if ((ptiCurrent->
pMenuState ==
NULL) ||
00189 (! ptiCurrent->
pMenuState->
fSetCapture)) {
00190
return;
00191 }
00192 ptiCurrent->
pMenuState->
fSetCapture =
FALSE;
00193
00194
00195
00196
00197
PtiCurrent()->pq->QF_flags &= ~
QF_CAPTURELOCKED;
00198
xxxReleaseCapture();
00199 }
00200
00201
00202
00203
00204
00205
00206 void MNCheckButtonDownState (
PMENUSTATE pMenuState)
00207 {
00208
00209
00210
00211
00212
00213 UserAssert(pMenuState->
fDragAndDrop || pMenuState->
fModelessMenu);
00214 pMenuState->
fButtonDown = ((
_GetKeyState(pMenuState->
vkButtonDown) & 0x8000) != 0);
00215
if (!pMenuState->
fButtonDown) {
00216 pMenuState->
fDragging =
00217 pMenuState->
fIgnoreButtonUp =
FALSE;
00218
UnlockMFMWFPWindow(&pMenuState->
uButtonDownHitArea);
00219 }
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 PWND GetMenuStateWindow (
PMENUSTATE pMenuState)
00233 {
00234
if (pMenuState ==
NULL) {
00235
return NULL;
00236 }
else if (pMenuState->
pGlobalPopupMenu->
fIsTrackPopup) {
00237
return pMenuState->
pGlobalPopupMenu->
spwndPopupMenu;
00238 }
else if (pMenuState->
pGlobalPopupMenu->
spwndNextPopup !=
NULL) {
00239
return pMenuState->
pGlobalPopupMenu->
spwndNextPopup;
00240 }
else {
00241
return pMenuState->
pGlobalPopupMenu->
spwndActivePopup;
00242 }
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 void UnlockPopupMenuWindow(
PMENU pmenu,
PWND pwnd)
00259 {
00260
00261
00262
00263
if ((pmenu ==
NULL)
00264 || (pmenu->
spwndNotify ==
NULL)) {
00265
return;
00266 }
00267
00268
00269
00270
if ((pmenu == pmenu->
spwndNotify->
spmenu)
00271 || (pmenu == pmenu->
spwndNotify->
spmenuSys)) {
00272
return;
00273 }
00274
00275
00276
00277
if ((pwnd != pmenu->
spwndNotify)
00278 && !
TestWF(pmenu->
spwndNotify,
WFDESTROYED)) {
00279
return;
00280 }
00281
00282
00283
00284
Unlock(&pmenu->
spwndNotify);
00285
return;
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 PVOID
LockPopupMenu(
PPOPUPMENU ppopup,
PMENU * pspmenu,
PMENU pmenu)
00297 {
00298
00299
00300
00301 UserAssert((pspmenu == &ppopup->
spmenu) || (pspmenu == &ppopup->
spmenuAlternate));
00302
Validateppopupmenu(ppopup);
00303
00304
00305
00306
00307 UserAssert(ppopup->
spwndNotify !=
NULL);
00308
00309
00310
00311
00312
00313
00314
#if DBG
00315
if ((*pspmenu !=
NULL)
00316 && ((*pspmenu)->spwndNotify !=
NULL)
00317 && ((*pspmenu)->spwndNotify != ppopup->
spwndNotify)) {
00318
00319 RIPMSG3(RIP_WARNING,
"LockPopupMenu: Current Menu %#p shared by %#p and %#p",
00320 *pspmenu, (*pspmenu)->spwndNotify, ppopup->
spwndNotify);
00321 }
00322
#endif
00323
00324
00325
00326
00327
UnlockPopupMenuWindow(*pspmenu, ppopup->
spwndNotify);
00328
00329
00330
00331
00332
if (pmenu !=
NULL) {
00333
00334
00335
00336
00337
#if DBG
00338
if ((pmenu->
spwndNotify !=
NULL)
00339 && (pmenu->
spwndNotify != ppopup->
spwndNotify)
00340 && (pmenu != pmenu->
spwndNotify->
head.rpdesk->spmenuDialogSys)) {
00341
00342 RIPMSG3(RIP_WARNING,
"LockPopupMenu: New Menu %#p shared by %#p and %#p",
00343 pmenu, pmenu->
spwndNotify, ppopup->
spwndNotify);
00344 }
00345
#endif
00346
00347
00348
00349
00350
Lock(&pmenu->
spwndNotify, ppopup->
spwndNotify);
00351 }
00352
00353
00354
00355
00356
return Lock(pspmenu, pmenu);
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 PVOID
UnlockPopupMenu(
PPOPUPMENU ppopup,
PMENU * pspmenu)
00368 {
00369
00370
00371
00372 UserAssert((pspmenu == &ppopup->
spmenu) || (pspmenu == &ppopup->
spmenuAlternate));
00373
00374
00375
00376
if (*pspmenu ==
NULL) {
00377
return NULL;
00378 }
00379
00380
00381
00382
00383
00384
00385 UserAssert((ppopup->
spwndNotify !=
NULL) ||
IsRootPopupMenu(ppopup));
00386
00387
00388
00389
00390
00391
00392
00393
#if DBG
00394
if (((*pspmenu)->spwndNotify !=
NULL)
00395 && (ppopup->spwndNotify !=
NULL)
00396 && (ppopup->spwndNotify != (*pspmenu)->spwndNotify)) {
00397
00398 RIPMSG3(RIP_WARNING,
"UnlockPopupMenu: Menu %#p shared by %#p and %#p",
00399 *pspmenu, (*pspmenu)->spwndNotify, ppopup->spwndNotify);
00400 }
00401
#endif
00402
00403
00404
00405
00406
UnlockPopupMenuWindow(*pspmenu, ppopup->spwndNotify);
00407
00408
00409
00410
00411
return Unlock(pspmenu);
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 PVOID
LockWndMenu(
PWND pwnd,
PMENU * pspmenu,
PMENU pmenu)
00423 {
00424
00425
00426
00427 UserAssert((pspmenu == &pwnd->
spmenu) || (pspmenu == &pwnd->
spmenuSys));
00428
00429
00430
00431
00432
if ((*pspmenu !=
NULL) && ((*pspmenu)->spwndNotify == pwnd)) {
00433
Unlock(&((*pspmenu)->spwndNotify));
00434 }
00435
00436
00437
00438
00439
if ((pmenu !=
NULL) && (pmenu->
spwndNotify ==
NULL)) {
00440
Lock(&pmenu->
spwndNotify, pwnd);
00441 }
00442
00443
00444
00445
00446
return Lock(pspmenu, pmenu);
00447
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 PVOID
UnlockWndMenu(
PWND pwnd,
PMENU * pspmenu)
00459 {
00460
00461
00462
00463 UserAssert((pspmenu == &pwnd->
spmenu) || (pspmenu == &pwnd->
spmenuSys));
00464
00465
00466
00467
00468
if (*pspmenu ==
NULL) {
00469
return NULL;
00470 }
00471
00472
00473
00474
00475
if (pwnd == (*pspmenu)->spwndNotify) {
00476
Unlock(&((*pspmenu)->spwndNotify));
00477 }
00478
00479
00480
00481
00482
return Unlock(pspmenu);
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 BOOL xxxMNSetTop(
PPOPUPMENU ppopup,
int iNewTop)
00496 {
00497
PMENU pMenu = ppopup->
spmenu;
00498
int dy;
00499
00500
if (iNewTop < 0) {
00501 iNewTop = 0;
00502 }
else if (iNewTop > pMenu->
iMaxTop) {
00503 iNewTop = pMenu->
iMaxTop;
00504 }
00505
00506
00507
00508
00509
if (iNewTop == pMenu->
iTop) {
00510
return FALSE;
00511 }
00512
00513
#if DBG
00514
00515
00516
00517 UserAssert((pMenu->
cyMax == 0) || (pMenu->
cyMax >= pMenu->
cyMenu));
00518
if ((
UINT)pMenu->
iMaxTop < pMenu->
cItems) {
00519
PITEM pitemLast = pMenu->
rgItems + pMenu->
cItems - 1;
00520
PITEM pitemMaxTop = pMenu->
rgItems + pMenu->
iMaxTop;
00521
UINT uHeight = pitemLast->
yItem + pitemLast->
cyItem - pitemMaxTop->
yItem;
00522 UserAssert(uHeight <= pMenu->cyMenu);
00523
00524
00525
00526 UserAssert(pMenu->
cyMenu - uHeight <= 2 * pitemLast->cyItem);
00527 }
else {
00528 UserAssert((
UINT)pMenu->
iMaxTop < pMenu->
cItems);
00529 }
00530
#endif
00531
00532
00533
00534
00535
00536
00537
00538
if (pMenu->
dwArrowsOn ==
MSA_ATTOP) {
00539 pMenu->
dwArrowsOn =
MSA_ON;
00540
if (pMenu->
hbrBack ==
NULL) {
00541
MNDrawArrow(
NULL, ppopup,
MFMWFP_UPARROW);
00542 }
00543 }
else if (pMenu->
dwArrowsOn ==
MSA_ATBOTTOM) {
00544 pMenu->
dwArrowsOn =
MSA_ON;
00545
if (pMenu->
hbrBack ==
NULL) {
00546
MNDrawArrow(
NULL, ppopup,
MFMWFP_DOWNARROW);
00547 }
00548 }
00549
00550 UserAssert((
UINT)iNewTop < pMenu->cItems);
00551 dy =
MNGetToppItem(pMenu)->
yItem - (pMenu->
rgItems + iNewTop)->yItem;
00552
00553
if ((dy > 0 ? dy : -dy) > (
int)pMenu->
cyMenu) {
00554
xxxInvalidateRect(ppopup->
spwndPopupMenu,
NULL,
TRUE);
00555 }
else {
00556
xxxScrollWindowEx(ppopup->
spwndPopupMenu, 0, dy,
NULL,
NULL,
NULL,
NULL, SW_INVALIDATE | SW_ERASE);
00557 }
00558
00559 pMenu->
iTop = iNewTop;
00560
00561
if (iNewTop == 0) {
00562 pMenu->
dwArrowsOn =
MSA_ATTOP;
00563
if (pMenu->
hbrBack ==
NULL) {
00564
MNDrawArrow(
NULL, ppopup,
MFMWFP_UPARROW);
00565 }
00566 }
else if (iNewTop == pMenu->
iMaxTop) {
00567 pMenu->
dwArrowsOn =
MSA_ATBOTTOM;
00568
if (pMenu->
hbrBack ==
NULL) {
00569
MNDrawArrow(
NULL, ppopup,
MFMWFP_DOWNARROW);
00570 }
00571 }
00572
00573
if (pMenu->
hbrBack !=
NULL) {
00574
MNDrawFullNC(ppopup->
spwndPopupMenu,
NULL, ppopup);
00575 }
00576
00577
return TRUE;
00578
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 BOOL xxxMNDoScroll(
PPOPUPMENU ppopup, UINT uArrow, BOOL fSetTimer)
00592 {
00593
int iScrollTop = ppopup->
spmenu->
iTop;
00594
00595
if (uArrow ==
MFMWFP_UPARROW) {
00596 iScrollTop--;
00597 }
else if (uArrow ==
MFMWFP_DOWNARROW) {
00598 iScrollTop++;
00599 }
else {
00600
return FALSE;
00601 }
00602
00603
if (!
xxxMNSetTop(ppopup, iScrollTop)) {
00604
if (!fSetTimer) {
00605
_KillTimer(ppopup->
spwndPopupMenu, uArrow);
00606 }
00607 }
else {
00608
00609
00610
00611
00612
_SetTimer(ppopup->
spwndPopupMenu, uArrow,
00613 (fSetTimer ?
gpsi->dtScroll :
gpsi->dtScroll / 4),
NULL);
00614 }
00615
00616
return TRUE;
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 int MNCheckScroll(
PMENU pMenu,
PMONITOR pMonitor)
00628 {
00629
int i;
00630
UINT cyMax;
00631
PITEM pItem;
00632
00633
00634
00635
00636 cyMax = (pMonitor->
rcMonitor.bottom - pMonitor->
rcMonitor.top);
00637
00638
00639
00640
00641
if ((pMenu->
cyMax != 0) && (pMenu->
cyMax < cyMax)) {
00642 cyMax = pMenu->
cyMax;
00643 }
00644
00645
00646
00647
00648
00649
if ((pMenu->
rgItems == 0)
00650 || (pMenu->
rgItems->
cxItem != pMenu->
cxMenu)
00651 || (pMenu->
cyMenu + (2 *
SYSMET(CYFIXEDFRAME)) <= cyMax)) {
00652
00653 pMenu->
dwArrowsOn =
MSA_OFF;
00654 pMenu->
iTop = 0;
00655 pMenu->
iMaxTop = 0;
00656
return pMenu->
cyMenu;
00657 }
00658
00659
00660
00661
00662 cyMax -= 2 * (
SYSMET(CYFIXEDFRAME) +
gcyMenuScrollArrow);
00663
00664
00665
00666
00667
00668 pItem = pMenu->
rgItems;
00669
for (i = 0; i < (
int)pMenu->
cItems; i++, pItem++) {
00670
if (pItem->
yItem > (
UINT)cyMax) {
00671
break;
00672 }
00673 }
00674
if (i != 0) {
00675 pItem--;
00676 }
00677 pMenu->
cyMenu = pItem->
yItem;
00678
00679
00680
00681
00682
00683 cyMax = 0;
00684 i = pMenu->
cItems - 1;
00685 pItem = pMenu->
rgItems + i;
00686
for (; i >= 0; i--, pItem--) {
00687 cyMax += pItem->
cyItem;
00688
if (cyMax > pMenu->
cyMenu) {
00689
break;
00690 }
00691 }
00692
if ((
UINT)i != pMenu->
cItems - 1) {
00693 i++;
00694 }
00695 pMenu->
iMaxTop = i;
00696
00697
00698
00699
00700
if (pMenu->
iTop > i) {
00701 pMenu->
iTop = i;
00702 }
00703
00704
if (pMenu->
iTop == i) {
00705 pMenu->
dwArrowsOn =
MSA_ATBOTTOM;
00706 }
else if (pMenu->
iTop == 0) {
00707 pMenu->
dwArrowsOn =
MSA_ATTOP;
00708 }
else {
00709 pMenu->
dwArrowsOn =
MSA_ON;
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
return (pMenu->
cyMenu + (2 *
gcyMenuScrollArrow));
00719 }
00720
00721
00722
00723
00724
00725
00726
00727 BOOL MNIsPopupItem(
ITEM *lpItem)
00728 {
00729
return((lpItem) && (lpItem->
spSubMenu) &&
00730 !
TestMFS(lpItem, MFS_GRAYED));
00731 }
00732
00733
00734
00735
00736
00737
00738
#if DBG
00739
void Validateppopupmenu (
PPOPUPMENU ppopupmenu)
00740 {
00741 UserAssert(ppopupmenu != NULL);
00742
try {
00743 UserAssert(!ppopupmenu->
fFreed);
00744
00745
00746
00747
00748
if (ppopupmenu->
ppopupmenuRoot !=
NULL) {
00749
if (ppopupmenu->
ppopupmenuRoot != ppopupmenu) {
00750
00751
00752
00753 UserAssert(ppopupmenu->
spwndPrevPopup != NULL);
00754 UserAssert(!ppopupmenu->
fIsMenuBar && !ppopupmenu->
fIsTrackPopup);
00755
Validateppopupmenu(ppopupmenu->
ppopupmenuRoot);
00756 }
else {
00757
00758
00759
00760 UserAssert(ppopupmenu->
spwndPrevPopup == NULL);
00761 UserAssert(ppopupmenu->
fIsMenuBar || ppopupmenu->
fIsTrackPopup);
00762 }
00763 }
00764
00765
00766
00767
00768
if (ppopupmenu->
spwndPopupMenu !=
NULL) {
00769 UserAssert(ppopupmenu->
spwndPopupMenu ==
RevalidateCatHwnd(
HW(ppopupmenu->
spwndPopupMenu)));
00770 }
00771
00772
00773
00774
00775
00776
if (ppopupmenu->
spwndNotify !=
NULL) {
00777 UserAssert(ppopupmenu->
spwndNotify ==
RevalidateCatHwnd(
HW(ppopupmenu->
spwndNotify)));
00778 }
00779
00780 } except (W32ExceptionHandler(FALSE, RIP_ERROR)) {
00781 RIPMSG1(RIP_ERROR,
"Validateppopupmenu: Invalid popup:%#p", ppopupmenu);
00782 }
00783 }
00784
#endif
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 BOOL xxxMNSwitchToAlternateMenu(
00796
PPOPUPMENU ppopupmenu)
00797 {
00798
PMENU pmenuSwap =
NULL;
00799
PMENUSTATE pMenuState;
00800
TL tlpwndPopupMenu;
00801
00802
if (!ppopupmenu->
fIsMenuBar || !ppopupmenu->
spmenuAlternate) {
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
return FALSE;
00816 }
00817
00818
00819
00820
00821
if (ppopupmenu->
fDestroyed) {
00822
return FALSE;
00823 }
00824
00825
00826
00827
00828
ThreadLock(ppopupmenu->
spwndPopupMenu, &tlpwndPopupMenu);
00829 UserAssert(ppopupmenu->
spwndPopupMenu !=
NULL);
00830 pMenuState =
GetpMenuState(ppopupmenu->
spwndPopupMenu);
00831
if (pMenuState ==
NULL) {
00832 RIPMSG0(RIP_ERROR,
"xxxMNSwitchToAlternateMenu: pMenuState == NULL");
00833
ThreadUnlock(&tlpwndPopupMenu);
00834
return FALSE;
00835 }
00836
xxxMNSelectItem(ppopupmenu, pMenuState,
MFMWFP_NOITEM);
00837
00838
00839 UserAssert(ppopupmenu->
spmenu->
spwndNotify == ppopupmenu->
spmenuAlternate->
spwndNotify);
00840
Lock(&pmenuSwap, ppopupmenu->
spmenuAlternate);
00841
Lock(&ppopupmenu->
spmenuAlternate, ppopupmenu->
spmenu);
00842
Lock(&ppopupmenu->
spmenu, pmenuSwap);
00843
Unlock(&pmenuSwap);
00844
00845
00846
00847
00848
if (!
TestWF(ppopupmenu->
spwndNotify,
WFSYSMENU)) {
00849 pMenuState->
fIsSysMenu =
FALSE;
00850 }
else if (ppopupmenu->
spwndNotify->
spmenuSys !=
NULL) {
00851 pMenuState->
fIsSysMenu = (ppopupmenu->
spwndNotify->
spmenuSys ==
00852 ppopupmenu->
spmenu);
00853 }
else {
00854 pMenuState->
fIsSysMenu = !!
TestMF(ppopupmenu->
spmenu,
MFSYSMENU);
00855 }
00856
00857 ppopupmenu->
fIsSysMenu = pMenuState->
fIsSysMenu;
00858
00859
if (
FWINABLE()) {
00860
xxxWindowEvent(EVENT_SYSTEM_MENUEND, ppopupmenu->
spwndNotify,
00861 (ppopupmenu->
fIsSysMenu ? OBJID_MENU : OBJID_SYSMENU), INDEXID_CONTAINER, 0);
00862
xxxWindowEvent(EVENT_SYSTEM_MENUSTART, ppopupmenu->
spwndNotify,
00863 (ppopupmenu->
fIsSysMenu ? OBJID_SYSMENU : OBJID_MENU), INDEXID_CONTAINER, 0);
00864 }
00865
00866
ThreadUnlock(&tlpwndPopupMenu);
00867
00868
return TRUE;
00869 }
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 void xxxMNDestroyHandler(
00881
PPOPUPMENU ppopupmenu)
00882 {
00883
PITEM pItem;
00884
TL tlpwndT;
00885
00886
if (ppopupmenu ==
NULL) {
00887
00888
00889
00890
00891 RIPMSG0(RIP_WARNING,
"xxxMNDestroyHandler: NULL \"ppopupmenu\"");
00892
return;
00893 }
00894
00895
#if DBG
00896
00897
00898
00899
00900
00901
00902
Validateppopupmenu(ppopupmenu);
00903
#endif
00904
00905
if (ppopupmenu->
spwndNextPopup !=
NULL) {
00906
00907
00908
00909
00910
00911
00912
00913
PWND pwnd;
00914 UserAssert(ppopupmenu->
spwndPopupMenu !=
NULL);
00915 pwnd = (ppopupmenu->
spwndPopupMenu !=
NULL ? ppopupmenu->
spwndPopupMenu : ppopupmenu->
spwndNextPopup);
00916
ThreadLockAlways(pwnd, &tlpwndT);
00917
xxxSendMessage(pwnd, MN_CLOSEHIERARCHY, 0, 0);
00918
ThreadUnlock(&tlpwndT);
00919 }
00920
00921
if ((ppopupmenu->
spmenu!=
NULL) &&
MNIsItemSelected(ppopupmenu))
00922 {
00923
00924
00925
00926
if (ppopupmenu->
posSelectedItem < ppopupmenu->
spmenu->
cItems) {
00927
00928
00929
00930
00931
00932
00933 pItem = &(ppopupmenu->
spmenu->
rgItems[ppopupmenu->
posSelectedItem]);
00934 pItem->
fState &= ~MFS_HILITE;
00935 }
00936 }
00937
00938
if (ppopupmenu->
fShowTimer) {
00939
_KillTimer(ppopupmenu->
spwndPopupMenu,
IDSYS_MNSHOW);
00940 }
00941
00942
if (ppopupmenu->
fHideTimer) {
00943
_KillTimer(ppopupmenu->
spwndPopupMenu,
IDSYS_MNHIDE);
00944 }
00945
00946
00947
00948
00949
if (ppopupmenu->
fSendUninit
00950 && (ppopupmenu->
spwndNotify !=
NULL)) {
00951
00952
ThreadLockAlways(ppopupmenu->
spwndNotify, &tlpwndT);
00953
xxxSendMessage(ppopupmenu->
spwndNotify, WM_UNINITMENUPOPUP,
00954 (WPARAM)
PtoH(ppopupmenu->
spmenu),
00955 MAKELONG(0, (ppopupmenu->
fIsSysMenu ? MF_SYSMENU: 0)));
00956
ThreadUnlock(&tlpwndT);
00957 }
00958
00959 ppopupmenu->
fDestroyed =
TRUE;
00960
if (!ppopupmenu->
fDesktopMenu) {
00961
00962
if (ppopupmenu->
spwndPopupMenu !=
NULL) {
00963 ((
PMENUWND)(ppopupmenu->
spwndPopupMenu))->ppopupmenu =
NULL;
00964 }
00965
00966 }
00967
00968
if (!ppopupmenu->
fDelayedFree) {
00969
MNFreePopup(ppopupmenu);
00970 }
else if (ppopupmenu->
ppopupmenuRoot !=
NULL) {
00971 ppopupmenu->
ppopupmenuRoot->
fFlushDelayedFree =
TRUE;
00972
#if DBG
00973
{
00974
00975
00976
00977
00978
if (!
IsRootPopupMenu(ppopupmenu)) {
00979
BOOL fFound =
FALSE;
00980
PPOPUPMENU ppm = ppopupmenu->
ppopupmenuRoot;
00981
while (ppm->
ppmDelayedFree !=
NULL) {
00982
if (ppm->
ppmDelayedFree == ppopupmenu) {
00983 fFound =
TRUE;
00984
break;
00985 }
00986 ppm = ppm->
ppmDelayedFree;
00987 }
00988 UserAssert(fFound);
00989 }
00990 }
00991
#endif
00992
}
else {
00993 UserAssertMsg1(
FALSE,
"Leaking ppopupmenu:%p?", ppopupmenu);
00994 }
00995
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011 void xxxMNChar(
01012
PPOPUPMENU ppopupmenu,
01013
PMENUSTATE pMenuState,
01014 UINT character)
01015 {
01016
PMENU pMenu;
01017
UINT flags;
01018 LRESULT result;
01019
int item;
01020
INT matchType;
01021
BOOL fExecute =
FALSE;
01022
TL tlpwndNotify;
01023
01024 pMenu = ppopupmenu->
spmenu;
01025
01026
Validateppopupmenu(ppopupmenu);
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
if (pMenu ==
NULL) {
01040 UserAssert(pMenu);
01041
xxxMNDismiss(pMenuState);
01042
return;
01043 }
01044
01045
01046
01047
01048
if (ppopupmenu->
fDestroyed) {
01049
return;
01050 }
01051
01052 item =
xxxMNFindChar(pMenu, character,
01053 ppopupmenu->
posSelectedItem, &matchType);
01054
if (item !=
MFMWFP_NOITEM) {
01055
int item1;
01056
int firstItem = item;
01057
01058
01059
01060
01061
01062
while (pMenu->
rgItems[item].
fState & MFS_GRAYED) {
01063 item =
xxxMNFindChar(pMenu, character, item, &matchType);
01064
if (item == firstItem) {
01065
xxxMNDismiss(pMenuState);
01066
return;
01067 }
01068 }
01069 item1 = item;
01070
01071
01072
01073
01074
01075
do {
01076 item =
xxxMNFindChar(pMenu, character, item, &matchType);
01077 }
while ((pMenu->
rgItems[item].
fState & MFS_GRAYED) && (item != firstItem));
01078
01079
if ((firstItem == item) || (item == item1))
01080 fExecute =
TRUE;
01081
01082 item = item1;
01083 }
01084
01085
if ((item ==
MFMWFP_NOITEM) && ppopupmenu->
fIsMenuBar && (character == TEXT(
' '))) {
01086
01087
01088
01089
01090
01091
01092
if (ppopupmenu->
fIsSysMenu) {
01093
01094
01095
01096
01097
01098 item = 0;
01099 fExecute =
TRUE;
01100 }
else if (ppopupmenu->
spmenuAlternate !=
NULL) {
01101
01102
01103
01104
01105
01106 item = 0;
01107
goto SwitchToAlternate;
01108 }
01109 }
01110
01111
if ((item ==
MFMWFP_NOITEM) && ppopupmenu->
fIsMenuBar && ppopupmenu->
spmenuAlternate) {
01112
01113
01114
01115
01116
01117 item =
xxxMNFindChar(ppopupmenu->
spmenuAlternate,
01118 character, 0, &matchType);
01119
01120
if (item !=
MFMWFP_NOITEM) {
01121 SwitchToAlternate:
01122
if (
xxxMNSwitchToAlternateMenu(ppopupmenu)) {
01123
xxxMNChar(ppopupmenu, pMenuState, character);
01124 }
01125
return;
01126 }
01127 }
01128
01129
if (item ==
MFMWFP_NOITEM) {
01130 flags = (ppopupmenu->
fIsSysMenu) ? MF_SYSMENU : 0;
01131
01132
if (!ppopupmenu->
fIsMenuBar) {
01133 flags |= MF_POPUP;
01134 }
01135
01136
ThreadLock(ppopupmenu->
spwndNotify, &tlpwndNotify);
01137 result =
xxxSendMessage(ppopupmenu->
spwndNotify, WM_MENUCHAR,
01138 MAKELONG((WORD)character, (WORD)flags),
01139 (LPARAM)
PtoH(ppopupmenu->
spmenu));
01140
ThreadUnlock(&tlpwndNotify);
01141
01142
switch (HIWORD(result)) {
01143
case MNC_IGNORE:
01144
xxxMessageBeep(0);
01145
01146
01147
01148
01149
01150
01151
if (flags & MF_POPUP) {
01152
return;
01153 }
01154
01155
01156
01157
01158
case MNC_CLOSE:
01159
xxxMNDismiss(pMenuState);
01160
return;
01161
01162
case MNC_EXECUTE:
01163 fExecute =
TRUE;
01164
01165
01166
case MNC_SELECT:
01167 item = (
UINT)(
short)LOWORD(result);
01168
if ((WORD) item >= ppopupmenu->
spmenu->
cItems)
01169 {
01170 RIPMSG1(RIP_WARNING,
"Invalid item number returned from WM_MENUCHAR %#lx", result);
01171
return;
01172 }
01173
break;
01174 }
01175 }
01176
01177
if (item !=
MFMWFP_NOITEM) {
01178
xxxMNSelectItem(ppopupmenu, pMenuState, item);
01179
01180
if (fExecute)
01181
xxxMNKeyDown(ppopupmenu, pMenuState, VK_RETURN);
01182 }
01183 }
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 DWORD GetMenuInheritedContextHelpId(
PPOPUPMENU ppopup)
01197 {
01198
PWND pWnd;
01199
01200
01201
01202
01203 UserAssert(ppopup !=
NULL);
01204
if (ppopup->
fIsMenuBar)
01205
goto Exit_GMI;
01206
01207
while(
TRUE) {
01208 UserAssert(ppopup !=
NULL);
01209
01210
01211
01212
01213
if (ppopup->
spmenu->
dwContextHelpId) {
01214
01215
break;
01216 }
01217
01218
01219
01220
01221
01222
if ( (ppopup->
fHasMenuBar) &&
01223 (ppopup->
spwndPrevPopup == ppopup->
spwndNotify)) {
01224
01225 ppopup = ppopup -> ppopupmenuRoot;
01226
break;
01227 }
else {
01228
01229
01230
01231
if ((pWnd = ppopup -> spwndPrevPopup) ==
NULL) {
01232
return ((
DWORD)0);
01233 }
01234
01235 ppopup = ((
PMENUWND)pWnd)->ppopupmenu;
01236 }
01237 }
01238
01239 Exit_GMI:
01240
return(ppopup->
spmenu->
dwContextHelpId);
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251 void xxxMNKeyDown(
01252
PPOPUPMENU ppopupmenu,
01253
PMENUSTATE pMenuState,
01254 UINT key)
01255 {
01256 LRESULT dwMDIMenu;
01257
UINT item;
01258
BOOL fHierarchyWasDropped =
FALSE;
01259
TL tlpwndT;
01260
PPOPUPMENU ppopupSave;
01261
BOOL bFakedKey;
01262
UINT keyOrig = key;
01263
01264
01265
01266
01267
if ((pMenuState->
fButtonDown) && (key != VK_F1)) {
01268
01269
01270
01271
if (pMenuState->
fDragging && (key == VK_ESCAPE)) {
01272 RIPMSG0(RIP_WARNING,
"xxxMNKeyDown: ESC while dragging");
01273 pMenuState->
fIgnoreButtonUp =
TRUE;
01274 }
01275
01276
return;
01277 }
01278
01279
switch (key) {
01280
case VK_MENU:
01281
case VK_F10:
01282 {
01283
01284
01285
01286
01287
if (pMenuState->
fModelessMenu) {
01288
return;
01289 }
01290
01291
if (
gwinOldAppHackoMaticFlags &
WOAHACK_CHECKALTKEYSTATE) {
01292
01293
01294
01295
01296
01297
01298
if (
gwinOldAppHackoMaticFlags &
WOAHACK_IGNOREALTKEYDOWN) {
01299
return;
01300 }
01301 }
01302
xxxMNDismiss(pMenuState);
01303
01304
01305
01306
01307
01308
if (key == VK_MENU) {
01309 pMenuState->
fUnderline =
FALSE;
01310 }
01311 }
01312
return;
01313
01314
case VK_ESCAPE:
01315
01316
01317
01318
01319
01320
01321
01322
if (ppopupmenu->
fIsMenuBar ||
01323 ppopupmenu == ppopupmenu->
ppopupmenuRoot ||
01324
TestWF(ppopupmenu->
ppopupmenuRoot->
spwndNotify,
WFMINIMIZED)) {
01325
xxxMNDismiss(pMenuState);
01326 }
else {
01327
01328
01329
01330
if (ppopupmenu->
fHasMenuBar &&
01331 ppopupmenu->
spwndPrevPopup == ppopupmenu->
spwndNotify) {
01332
01333
PPOPUPMENU ppopupmenuRoot = ppopupmenu->
ppopupmenuRoot;
01334
01335 ppopupmenuRoot->
fDropNextPopup =
FALSE;
01336
01337
#if 0
01338
01339
01340
01341
01342
01343
if (
_IsIconic(ppopupmenuRoot->
spwndNotify)) {
01344
01345
01346
01347
01348
01349
01350
xxxMNDismiss(pMenuState);
01351 }
else
01352
#endif
01353
01354
01355
01356
01357
01358
01359
if (pMenuState->
fModelessMenu) {
01360
xxxMNDismiss(pMenuState);
01361 }
else {
01362
xxxMNCloseHierarchy(ppopupmenuRoot, pMenuState);
01363 }
01364 }
else {
01365
ThreadLock(ppopupmenu->
spwndPrevPopup, &tlpwndT);
01366
xxxSendMessage(ppopupmenu->
spwndPrevPopup, MN_CLOSEHIERARCHY,
01367 0, 0);
01368
ThreadUnlock(&tlpwndT);
01369 }
01370 }
01371
return;
01372
01373
case VK_UP:
01374
case VK_DOWN:
01375
if (ppopupmenu->
fIsMenuBar) {
01376
01377
01378
01379
01380
01381
if (
xxxMNOpenHierarchy(ppopupmenu, pMenuState) == (
PWND)-1)
01382
return;
01383 }
else {
01384 item =
MNFindNextValidItem(ppopupmenu->
spmenu,
01385 ppopupmenu->
posSelectedItem, (key == VK_UP ? -1 : 1), 0);
01386
xxxMNSelectItem(ppopupmenu, pMenuState, item);
01387 }
01388
return;
01389
01390
case VK_LEFT:
01391
case VK_RIGHT:
01392
#ifdef USE_MIRRORING
01393
bFakedKey = (!!ppopupmenu->
fRtoL) ^ (!!
TestWF(ppopupmenu->
spwndPopupMenu, WEFLAYOUTRTL));
01394
#else
01395
bFakedKey = ppopupmenu->
fRtoL;
01396
#endif
01397
if (bFakedKey)
01398
01399
01400
01401 key = (key == VK_LEFT) ? VK_RIGHT : VK_LEFT;
01402
if (!ppopupmenu->
fIsMenuBar && (key == VK_RIGHT) &&
01403 !ppopupmenu->
spwndNextPopup) {
01404
01405
01406
01407
if (
xxxMNOpenHierarchy(ppopupmenu, pMenuState) == (
PWND)-1)
01408
return;
01409
if (ppopupmenu->
fHierarchyDropped) {
01410
return;
01411 }
01412 }
01413
01414
if (ppopupmenu->
spwndNextPopup) {
01415 fHierarchyWasDropped =
TRUE;
01416
if ((key == VK_LEFT) && !ppopupmenu->
fIsMenuBar) {
01417
xxxMNCloseHierarchy(ppopupmenu, pMenuState);
01418
return;
01419 }
01420 }
else if (ppopupmenu->
fDropNextPopup)
01421 fHierarchyWasDropped =
TRUE;
01422
01423 ppopupSave = ppopupmenu;
01424
01425 item =
MNFindItemInColumn(ppopupmenu->spmenu,
01426 ppopupmenu->posSelectedItem,
01427 (key == VK_LEFT ? -1 : 1),
01428 (ppopupmenu->fHasMenuBar &&
01429 ppopupmenu == ppopupmenu->ppopupmenuRoot));
01430
01431
if (item ==
MFMWFP_NOITEM) {
01432
01433
01434
01435
01436
01437
if (ppopupmenu->fHasMenuBar &&
01438 ppopupmenu->spwndPrevPopup == ppopupmenu->spwndNotify) {
01439
01440
01441
01442
01443
if (bFakedKey)
01444 key = (key == VK_LEFT) ? VK_RIGHT : VK_LEFT;
01445
01446
01447
01448
01449
xxxMNKeyDown(ppopupmenu->ppopupmenuRoot, pMenuState, key);
01450
return;
01451 }
01452
01453
if (ppopupmenu == ppopupmenu->ppopupmenuRoot) {
01454
if (!ppopupmenu->fIsMenuBar) {
01455
01456
01457
01458
01459
return;
01460 }
01461 }
else {
01462
ThreadLock(ppopupmenu->spwndPrevPopup, &tlpwndT);
01463
xxxSendMessage(ppopupmenu->spwndPrevPopup, WM_KEYDOWN, keyOrig, 0);
01464
ThreadUnlock(&tlpwndT);
01465
return;
01466 }
01467 }
01468
01469
if (!ppopupmenu->fIsMenuBar) {
01470
if (item !=
MFMWFP_NOITEM) {
01471
xxxMNSelectItem(ppopupmenu, pMenuState, item);
01472 }
01473
return;
01474
01475 }
else {
01476
01477
01478
01479
01480
if (item ==
MFMWFP_NOITEM) {
01481
01482
if (
TestWF(ppopupmenu->spwndNotify,
WFSYSMENU)) {
01483
PTHREADINFO ptiCurrent =
PtiCurrent();
01484
PWND pwndNextMenu;
01485
PMENU pmenuNextMenu, pmenuUse;
01486 MDINEXTMENU mnm;
01487
TL tlpmenuNextMenu;
01488
TL tlpwndNextMenu;
01489
01490 mnm.hmenuIn = (HMENU)0;
01491 mnm.hmenuNext = (HMENU)0;
01492 mnm.hwndNext = (HWND)0;
01493
01494
01495
01496
01497
01498 pmenuNextMenu = ppopupmenu->fIsSysMenu ?
01499
_GetSubMenu(ppopupmenu->spmenu, 0) :
01500 ppopupmenu->spmenu;
01501 mnm.hmenuIn =
PtoH(pmenuNextMenu);
01502
ThreadLock(ppopupmenu->spwndNotify, &tlpwndT);
01503 dwMDIMenu =
xxxSendMessage(ppopupmenu->spwndNotify,
01504 WM_NEXTMENU, (WPARAM)keyOrig, (LPARAM)&mnm);
01505
ThreadUnlock(&tlpwndT);
01506
01507 pwndNextMenu =
RevalidateHwnd(mnm.hwndNext);
01508
if (pwndNextMenu ==
NULL)
01509
goto TryAlternate;
01510
01511
01512
01513
01514
01515
01516
if (
GETPTI(pwndNextMenu) != ptiCurrent) {
01517 RIPMSG1(RIP_WARNING,
"xxxMNKeyDown: Ignoring mnm.hwndNext bacause it belongs to another thread: %#p", pwndNextMenu);
01518
goto TryAlternate;
01519 }
01520
01521
01522 pmenuNextMenu =
RevalidateHmenu(mnm.hmenuNext);
01523
if (pmenuNextMenu ==
NULL)
01524
goto TryAlternate;
01525
01526
ThreadLock(pmenuNextMenu, &tlpmenuNextMenu);
01527
ThreadLock(pwndNextMenu, &tlpwndNextMenu);
01528
01529
01530
01531
01532
01533
01534
if (
TestWF(pwndNextMenu,
WFMINIMIZED))
01535 fHierarchyWasDropped =
TRUE;
01536
01537
xxxMNSelectItem(ppopupmenu, pMenuState,
MFMWFP_NOITEM);
01538
01539 pMenuState->
fIsSysMenu =
TRUE;
01540
UnlockPopupMenu(ppopupmenu, &ppopupmenu->spmenuAlternate);
01541 ppopupmenu->fToggle =
FALSE;
01542
01543
01544
01545
01546
01547 pmenuUse = (((pwndNextMenu->
spmenuSys !=
NULL)
01548 && (
_GetSubMenu(pwndNextMenu->
spmenuSys, 0) == pmenuNextMenu))
01549 ? pwndNextMenu->
spmenuSys
01550 : pmenuNextMenu);
01551
01552
01553
01554
01555
01556
01557
01558
01559 UserAssert(
IsRootPopupMenu(ppopupmenu));
01560
UnlockPopupMenu(ppopupmenu, &ppopupmenu->spmenu);
01561
Lock(&ppopupmenu->spwndNotify, pwndNextMenu);
01562
Lock(&ppopupmenu->spwndPopupMenu, pwndNextMenu);
01563
LockPopupMenu(ppopupmenu, &ppopupmenu->spmenu, pmenuUse);
01564
01565
01566
01567
01568
if (!pMenuState->
fModelessMenu) {
01569 ptiCurrent->
pq->
QF_flags &= ~
QF_CAPTURELOCKED;
01570
xxxMNSetCapture(ppopupmenu);
01571 }
01572
01573
01574
if (!
TestWF(pwndNextMenu,
WFCHILD) &&
01575 ppopupmenu->spmenu !=
NULL) {
01576
01577
01578
01579
01580
01581
if (pwndNextMenu->
spmenu == ppopupmenu->spmenu) {
01582
LockPopupMenu(ppopupmenu, &ppopupmenu->spmenuAlternate,
01583 pwndNextMenu->
spmenuSys);
01584 pMenuState->
fIsSysMenu =
FALSE;
01585 }
else {
01586
LockPopupMenu(ppopupmenu, &ppopupmenu->spmenuAlternate,
01587 pwndNextMenu->
spmenu);
01588 }
01589 }
01590
01591
ThreadUnlock(&tlpwndNextMenu);
01592
ThreadUnlock(&tlpmenuNextMenu);
01593
01594 ppopupmenu->fIsSysMenu = pMenuState->
fIsSysMenu;
01595
01596 item = 0;
01597 }
else
01598 TryAlternate:
01599
if (
xxxMNSwitchToAlternateMenu(ppopupmenu)) {
01600
01601
01602
01603
01604
int dir = (key == VK_RIGHT) ? 1 : -1;
01605
01606 item =
MNFindNextValidItem(ppopupmenu->spmenu,
MFMWFP_NOITEM,
dir, 0);
01607 }
01608 }
01609
01610
if (item !=
MFMWFP_NOITEM) {
01611
01612
01613
01614
01615
01616
01617
01618
if (ppopupSave->
spwndNextPopup)
01619
xxxMNCloseHierarchy(ppopupSave, pMenuState);
01620
01621
xxxMNSelectItem(ppopupmenu, pMenuState, item);
01622
01623
if (fHierarchyWasDropped) {
01624 DropHierarchy:
01625
if (
xxxMNOpenHierarchy(ppopupmenu, pMenuState) == (
PWND)-1) {
01626
return;
01627 }
01628 }
01629 }
01630 }
01631
return;
01632
01633
case VK_RETURN:
01634 {
01635
BOOL fEnabled;
01636
PITEM pItem;
01637
01638
if (ppopupmenu->posSelectedItem >= ppopupmenu->spmenu->cItems) {
01639
xxxMNDismiss(pMenuState);
01640
return;
01641 }
01642
01643 pItem = ppopupmenu->spmenu->rgItems + ppopupmenu->posSelectedItem;
01644 fEnabled = !(pItem->
fState & MFS_GRAYED);
01645
if ((pItem->
spSubMenu !=
NULL) && fEnabled)
01646
goto DropHierarchy;
01647
01648
01649
01650
01651
if (fEnabled) {
01652
xxxMNDismissWithNotify(pMenuState, ppopupmenu->spmenu, pItem, ppopupmenu->posSelectedItem, 0);
01653 }
else {
01654
xxxMNDismiss(pMenuState);
01655 }
01656
return;
01657 }
01658
01659
case VK_F1:
01660 {
01661
PITEM pItem;
01662
01663 pItem = ppopupmenu->spmenu->rgItems + ppopupmenu->posSelectedItem;
01664
ThreadLock(ppopupmenu->spwndNotify, &tlpwndT);
01665
xxxSendHelpMessage(ppopupmenu->spwndNotify, HELPINFO_MENUITEM, pItem->
wID,
01666
PtoHq(ppopupmenu->spmenu),
01667
GetMenuInheritedContextHelpId(ppopupmenu));
01668
ThreadUnlock(&tlpwndT);
01669
break;
01670 }
01671
01672 }
01673 }
01674
01675
01676
01677
01678
01679
01680
01681
01682
UINT
01683 xxxMNPositionHierarchy(
01684
PPOPUPMENU ppopup,
01685
PITEM pitem,
01686
int cx,
01687
int cy,
01688
int *px,
01689
int *py,
01690
PMONITOR *ppMonitor)
01691 {
01692
int x, y;
01693
UINT uPAS;
01694
PMONITOR pMonitor;
01695
01696 UserAssert(ppopup->
fHierarchyDropped && (ppopup->
spwndNextPopup !=
NULL));
01697
01698
if (ppopup->
fIsMenuBar) {
01699
01700
01701
01702
01703
01704
01705
BOOL fIconic = (
TestWF(ppopup->
spwndPopupMenu,
WFMINIMIZED) != 0);
01706 RECT rcWindow;
01707
01708
01709
01710
01711 uPAS =
PAS_DOWN;
01712
01713
CopyRect(&rcWindow, &ppopup->
spwndPopupMenu->
rcWindow);
01714
if (fIconic &&
IsTrayWindow(ppopup->
spwndPopupMenu)) {
01715
xxxSendMinRectMessages(ppopup->
spwndPopupMenu, &rcWindow);
01716 }
01717
01718
01719
01720
01721
if (!
SYSMET(MENUDROPALIGNMENT) && !
TestMF(ppopup->
spmenu,
MFRTL)) {
01722
if (fIconic) {
01723 x = rcWindow.left;
01724 }
else {
01725 x = rcWindow.left + pitem->
xItem;
01726 }
01727 }
else {
01728 ppopup->
fDroppedLeft =
TRUE;
01729
if (fIconic) {
01730 x = rcWindow.right - cx;
01731 }
else {
01732 x = rcWindow.left + pitem->
xItem + pitem->
cxItem - cx;
01733 }
01734 }
01735
01736
01737
01738
01739
01740
01741
if (!fIconic)
01742 {
01743
01744
01745
01746
01747
01748 rcWindow.left += pitem->
xItem;
01749 rcWindow.top += pitem->
yItem;
01750 rcWindow.right = rcWindow.left + pitem->
cxItem;
01751 rcWindow.bottom = rcWindow.top + pitem->
cyItem;
01752 }
01753
01754 pMonitor =
_MonitorFromRect(&rcWindow, MONITOR_DEFAULTTOPRIMARY);
01755
01756
01757
01758
01759
if (!fIconic) {
01760 y = rcWindow.bottom;
01761 }
else {
01762
01763
01764
01765
01766 y = rcWindow.top -
cy;
01767
if (y < pMonitor->
rcMonitor.top) {
01768 y = rcWindow.bottom;
01769 }
01770 }
01771
01772
01773
01774
01775 x =
min(x, pMonitor->
rcMonitor.right - cx);
01776
01777
#ifdef USE_MIRRORING
01778
if (
TestWF(ppopup->
spwndPopupMenu, WEFLAYOUTRTL)) {
01779 x = ppopup->
spwndPopupMenu->
rcWindow.right - x + ppopup->
spwndPopupMenu->
rcWindow.left - cx;
01780 }
01781
#endif
01782
01783 }
else {
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793 uPAS =
PAS_RIGHT;
01794 x = ppopup->
spwndPopupMenu->
rcWindow.left + pitem->
xItem + pitem->
cxItem;
01795
01796
01797
01798
01799 y = ppopup->
spwndPopupMenu->
rcWindow.top + pitem->
yItem;
01800
if (ppopup->
spmenu->
dwArrowsOn !=
MSA_OFF) {
01801 y +=
gcyMenuScrollArrow -
MNGetToppItem(ppopup->
spmenu)->
yItem;
01802 }
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812 pMonitor =
_MonitorFromWindow(
01813 ppopup->
spwndPopupMenu, MONITOR_DEFAULTTOPRIMARY);
01814
01815
#ifdef USE_MIRRORING
01816
if ((!!ppopup->
fDroppedLeft) ^ (!!
TestWF(ppopup->
spwndPopupMenu, WEFLAYOUTRTL))) {
01817
#else
01818
if (ppopup->
fDroppedLeft) {
01819
#endif
01820
int xTmp;
01821
01822
01823
01824
01825
01826 xTmp = ppopup->
spwndPopupMenu->
rcWindow.left +
SYSMET(CXFIXEDFRAME) - cx;
01827
if (xTmp >= pMonitor->
rcMonitor.left) {
01828 x = xTmp;
01829 uPAS =
PAS_LEFT;
01830 }
01831 }
01832
01833
01834
01835
01836
01837
if (x + cx > pMonitor->
rcMonitor.right) {
01838 x = ppopup->
spwndPopupMenu->
rcWindow.left +
SYSMET(CXFIXEDFRAME) - cx;
01839 uPAS =
PAS_LEFT;
01840 }
01841
#ifdef USE_MIRRORING
01842
if (
TestWF(ppopup->
spwndPopupMenu, WEFLAYOUTRTL)) {
01843 uPAS ^=
PAS_HORZ;
01844 }
01845
#endif
01846
01847 }
01848
01849
01850
01851
01852 UserAssert(pMonitor);
01853
if (y +
cy > pMonitor->
rcMonitor.bottom) {
01854 y -=
cy;
01855
01856
01857
01858
01859
if (ppopup->
fIsMenuBar) {
01860 y -=
SYSMET(CYMENUSIZE);
01861
if (y >= pMonitor->
rcMonitor.top) {
01862 uPAS =
PAS_UP;
01863 }
01864 }
else {
01865
01866
01867
01868 y += pitem->
cyItem + 2*
SYSMET(CYFIXEDFRAME);
01869 }
01870
01871
01872
01873
01874
if ( (y < pMonitor->
rcMonitor.top) ||
01875 (y +
cy > pMonitor->
rcMonitor.bottom))
01876
01877
01878
01879 y = pMonitor->
rcMonitor.bottom -
cy;
01880 }
01881
01882
01883
01884
01885 x =
max(x, pMonitor->
rcMonitor.left);
01886 y =
max(y, pMonitor->
rcMonitor.top);
01887
01888
01889
01890
01891 *px = x;
01892 *py = y;
01893 *ppMonitor = pMonitor;
01894
01895
01896
01897
01898
return uPAS;
01899 }
01900
01901
01902
01903
01904
01905
01906
01907
01908 void xxxCleanupDesktopMenu (
PWND pwndDeskMenu,
PDESKTOP pdesk)
01909 {
01910
TL tlpwnd;
01911
CheckLock(pwndDeskMenu);
01912
01913
01914
01915 UserAssert(pwndDeskMenu->
spwndParent ==
_GetDesktopWindow());
01916
ThreadLockAlways(pdesk->
spwndMessage, &tlpwnd);
01917
xxxSetParent(pwndDeskMenu, pdesk->
spwndMessage);
01918
ThreadUnlock(&tlpwnd);
01919
01920
01921
01922
01923 pwndDeskMenu->
head.pti = pdesk->
pDeskInfo->
spwnd->
head.pti;
01924
Unlock(&pwndDeskMenu->
spwndOwner);
01925 }
01926
01927
01928
01929
01930
01931
01932
01933
01934 PWND xxxMNOpenHierarchy(
01935
PPOPUPMENU ppopupmenu,
PMENUSTATE pMenuState)
01936 {
01937
PWND ret = 0;
01938
PITEM pItem;
01939
PWND pwndHierarchy;
01940
PPOPUPMENU ppopupmenuHierarchy;
01941 LONG sizeHierarchy;
01942
int xLeft;
01943
int yTop;
01944
int cxPopup, cyPopup;
01945
TL tlpwndT;
01946
TL tlpwndHierarchy;
01947
PTHREADINFO ptiCurrent =
PtiCurrent();
01948
PDESKTOP pdesk = ptiCurrent->
rpdesk;
01949
BOOL fSendUninit =
FALSE;
01950 HMENU hmenuInit;
01951
PMONITOR pMonitor;
01952
01953
01954
if (ppopupmenu->
posSelectedItem ==
MFMWFP_NOITEM) {
01955
01956
01957
01958
return NULL;
01959 }
01960
01961
if (ppopupmenu->
posSelectedItem >= ppopupmenu->
spmenu->
cItems)
01962
return NULL;
01963
01964
if (ppopupmenu->
fHierarchyDropped) {
01965
if (ppopupmenu->
fHideTimer) {
01966
xxxMNCloseHierarchy(ppopupmenu,pMenuState);
01967 }
else {
01968
01969
01970
01971 UserAssert(!ppopupmenu->
fHierarchyDropped);
01972
return NULL;
01973 }
01974 }
01975
01976
if (ppopupmenu->
fShowTimer) {
01977
_KillTimer(ppopupmenu->
spwndPopupMenu,
IDSYS_MNSHOW);
01978 ppopupmenu->
fShowTimer =
FALSE;
01979 }
01980
01981
01982
01983
01984 pItem = &(ppopupmenu->
spmenu->
rgItems[ppopupmenu->
posSelectedItem]);
01985
01986
if (pItem->
spSubMenu ==
NULL)
01987
goto Exit;
01988
01989
01990
01991
01992
if (!ppopupmenu->
fNoNotify) {
01993
ThreadLock(ppopupmenu->
spwndNotify, &tlpwndT);
01994
01995
01996
01997
01998
01999 hmenuInit =
PtoHq(pItem->
spSubMenu);
02000
xxxSendMessage(ppopupmenu->
spwndNotify, WM_INITMENUPOPUP,
02001 (WPARAM)hmenuInit, MAKELONG(ppopupmenu->
posSelectedItem,
02002 (ppopupmenu->
fIsSysMenu ? 1: 0)));
02003
ThreadUnlock(&tlpwndT);
02004 fSendUninit =
TRUE;
02005 }
02006
02007
02008
02009
02010
02011
02012
if (!pMenuState->
fInsideMenuLoop) {
02013 RIPMSG0(RIP_WARNING,
"Menu loop ended unexpectedly by WM_INITMENUPOPUP");
02014 ret = (
PWND)-1;
02015
goto Exit;
02016 }
02017
02018
02019
02020
02021
02022
if (ppopupmenu->
posSelectedItem >= ppopupmenu->
spmenu->
cItems) {
02023
02024
02025
02026
goto Exit;
02027 }
02028
02029
02030
02031
02032
02033 pItem = &(ppopupmenu->
spmenu->
rgItems[ppopupmenu->
posSelectedItem]);
02034
02035
if (
TestMFS(pItem, MFS_GRAYED) || (pItem->
spSubMenu ==
NULL) || (pItem->
spSubMenu->
cItems == 0)) {
02036
02037
02038
02039
02040
02041
02042
goto Exit;
02043 }
02044
02045
02046
02047
02048
02049
02050 UserAssert(ptiCurrent->
pMenuState == pMenuState);
02051
02052
if (ppopupmenu->
fIsMenuBar && (pdesk->
spwndMenu !=
NULL) &&
02053 (!(pdesk->
dwDTFlags &
DF_MENUINUSE)) &&
02054 !
TestWF(pdesk->
spwndMenu,
WFVISIBLE)) {
02055
02056 pdesk->
dwDTFlags |=
DF_MENUINUSE;
02057
02058
if (
HMPheFromObject(pdesk->
spwndMenu)->bFlags &
HANDLEF_DESTROY) {
02059
PPROCESSINFO ppi = pdesk->
rpwinstaParent->
pTerm->
ptiDesktop->
ppi;
02060
PPROCESSINFO ppiSave;
02061
PWND pwndMenu;
02062
DWORD dwDisableHooks;
02063
02064
02065
02066
02067
02068
02069
02070 UserAssert(ppopupmenu->
fDesktopMenu);
02071
02072 ppopupmenu->
fDesktopMenu =
FALSE;
02073 ppopupmenu->
fDelayedFree =
FALSE;
02074
02075
Unlock(&pdesk->
spwndMenu);
02076 ppiSave = ptiCurrent->
ppi;
02077 ptiCurrent->
ppi = ppi;
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089 dwDisableHooks = ptiCurrent->
TIF_flags &
TIF_DISABLEHOOKS;
02090 ptiCurrent->
TIF_flags |=
TIF_DISABLEHOOKS;
02091
02092 pwndMenu =
xxxCreateWindowEx(
02093 WS_EX_TOOLWINDOW | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE,
02094 (
PLARGE_STRING)
MENUCLASS,
02095
NULL,
02096 WS_POPUP | WS_BORDER,
02097 0,
02098 0,
02099 100,
02100 100,
02101
NULL,
02102
NULL,
02103
hModuleWin,
02104
NULL,
02105 WINVER);
02106
02107 UserAssert(ptiCurrent->
TIF_flags &
TIF_DISABLEHOOKS);
02108 ptiCurrent->
TIF_flags = (ptiCurrent->
TIF_flags & ~
TIF_DISABLEHOOKS) | dwDisableHooks;
02109
02110
Lock(&(pdesk->
spwndMenu), pwndMenu);
02111
02112 UserAssert(((
PMENUWND)pwndMenu)->ppopupmenu !=
NULL);
02113
02114
02115
02116
02117
02118
02119 ((
PMENUWND)pwndMenu)->ppopupmenu->fDesktopMenu =
TRUE;
02120
Unlock(&((
PMENUWND)pwndMenu)->ppopupmenu->
spwndPopupMenu);
02121
02122 ptiCurrent->
ppi = ppiSave;
02123
02124
HMChangeOwnerThread(pdesk->
spwndMenu, pdesk->
rpwinstaParent->
pTerm->
ptiDesktop);
02125 }
else {
02126
TL tlpwndDesk;
02127
02128
ThreadLockAlways(pdesk->
spwndMenu, &tlpwndT);
02129
ThreadLockAlways(pdesk->
pDeskInfo->
spwnd, &tlpwndDesk);
02130
xxxSetParent(pdesk->
spwndMenu, pdesk->
pDeskInfo->
spwnd);
02131
ThreadUnlock(&tlpwndDesk);
02132
ThreadUnlock(&tlpwndT);
02133
02134 }
02135
02136
02137 pwndHierarchy = pdesk->
spwndMenu;
02138
Lock(&pwndHierarchy->
spwndOwner, ppopupmenu->
spwndNotify);
02139 pwndHierarchy->
head.pti = ptiCurrent;
02140
02141
02142
02143
02144
if ((
TestWF(pdesk->
spwndMenu,
WEFTOPMOST) && pMenuState->
fModelessMenu)
02145 || (!
TestWF(pdesk->
spwndMenu,
WEFTOPMOST) && !pMenuState->
fModelessMenu)) {
02146
02147
ThreadLock(pdesk->
spwndMenu, &tlpwndHierarchy);
02148
xxxSetWindowPos(pdesk->
spwndMenu,
02149 (pMenuState->
fModelessMenu ? PWND_NOTOPMOST:
PWND_TOPMOST),
02150 0,0,0,0,
02151 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
02152
ThreadUnlock(&tlpwndHierarchy);
02153 }
02154
02155 ppopupmenuHierarchy = ((
PMENUWND)pwndHierarchy)->ppopupmenu;
02156
02157 UserAssert(ppopupmenuHierarchy->
fDesktopMenu);
02158
02159
02160
02161
02162 UserAssert(ppopupmenuHierarchy->
spwndPopupMenu ==
NULL);
02163 UserAssert(ppopupmenuHierarchy->
spwndNextPopup ==
NULL);
02164 UserAssert(ppopupmenuHierarchy->
spwndPrevPopup ==
NULL);
02165 UserAssert(ppopupmenuHierarchy->
spmenu ==
NULL);
02166 UserAssert(ppopupmenuHierarchy->
spmenuAlternate ==
NULL);
02167 UserAssert(ppopupmenuHierarchy->
spwndNotify ==
NULL);
02168 UserAssert(ppopupmenuHierarchy->
spwndActivePopup ==
NULL);
02169
02170 RtlZeroMemory((PVOID)ppopupmenuHierarchy,
sizeof(
POPUPMENU));
02171 ppopupmenuHierarchy->fDesktopMenu =
TRUE;
02172
02173 ppopupmenuHierarchy->posSelectedItem =
MFMWFP_NOITEM;
02174
Lock(&ppopupmenuHierarchy->spwndPopupMenu, pdesk->
spwndMenu);
02175
02176
Lock(&(ppopupmenuHierarchy->spwndNotify), ppopupmenu->
spwndNotify);
02177
LockPopupMenu(ppopupmenuHierarchy, &ppopupmenuHierarchy->spmenu, pItem->
spSubMenu);
02178
02179 }
else {
02180
02181
ThreadLock(ppopupmenu->
spwndNotify, &tlpwndT);
02182
02183 pwndHierarchy =
xxxCreateWindowEx(
02184 WS_EX_TOOLWINDOW | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE,
02185 (
PLARGE_STRING)
MENUCLASS,
NULL,
02186 WS_POPUP | WS_BORDER, 0, 0, 100, 100, ppopupmenu->
spwndNotify,
02187
NULL, (HANDLE)ppopupmenu->
spwndNotify->hModule,
02188 (
LPVOID)pItem->
spSubMenu, WINVER);
02189
02190
ThreadUnlock(&tlpwndT);
02191
02192
if (!pwndHierarchy)
02193
goto Exit;
02194
02195
02196
02197
02198
02199
ClrWF(pwndHierarchy,
WFOLDUI);
02200
02201 ppopupmenuHierarchy = ((
PMENUWND)pwndHierarchy)->ppopupmenu;
02202
02203 }
02204
02205
02206
02207
02208 ppopupmenuHierarchy->
fDelayedFree =
TRUE;
02209 ppopupmenuHierarchy->
ppmDelayedFree = ppopupmenu->
ppopupmenuRoot->
ppmDelayedFree;
02210 ppopupmenu->
ppopupmenuRoot->
ppmDelayedFree = ppopupmenuHierarchy;
02211
02212
#ifdef USE_MIRRORING
02213
if (
TestWF(ppopupmenu->
spwndPopupMenu, WEFLAYOUTRTL)) {
02214
SetWF(pwndHierarchy, WEFLAYOUTRTL);
02215 }
else {
02216
ClrWF(pwndHierarchy, WEFLAYOUTRTL);
02217 }
02218
#endif
02219
02220
02221
Lock(&(ppopupmenuHierarchy->
spwndNotify), ppopupmenu->
spwndNotify);
02222
#if DBG
02223
02224
02225
02226
02227
02228
if (!ppopupmenu->
fNoNotify && (hmenuInit !=
PtoHq(pItem->
spSubMenu))) {
02229 RIPMSG2(RIP_WARNING,
"xxxMNOpenHierarchy: bad app changed submenu from %#p to %#p",
02230 hmenuInit,
PtoHq(pItem->
spSubMenu));
02231 }
02232
#endif
02233
LockPopupMenu(ppopupmenuHierarchy, &ppopupmenuHierarchy->
spmenu, pItem->
spSubMenu);
02234
Lock(&(ppopupmenu->
spwndNextPopup), pwndHierarchy);
02235 ppopupmenu->
posDropped = ppopupmenu->
posSelectedItem;
02236
Lock(&(ppopupmenuHierarchy->
spwndPrevPopup), ppopupmenu->
spwndPopupMenu);
02237 ppopupmenuHierarchy->
ppopupmenuRoot = ppopupmenu->
ppopupmenuRoot;
02238 ppopupmenuHierarchy->
fHasMenuBar = ppopupmenu->
fHasMenuBar;
02239 ppopupmenuHierarchy->
fIsSysMenu = ppopupmenu->
fIsSysMenu;
02240 ppopupmenuHierarchy->
fNoNotify = ppopupmenu->
fNoNotify;
02241 ppopupmenuHierarchy->
fSendUninit =
TRUE;
02242 ppopupmenuHierarchy->
fRtoL = ppopupmenu->
fRtoL;
02243
02244
02245
02246
02247
02248
02249 fSendUninit =
FALSE;
02250
02251
02252
02253
02254
if (pMenuState->
fUnderline) {
02255
SetMF(ppopupmenuHierarchy->
spmenu,
MFUNDERLINE);
02256 }
else {
02257
ClearMF(ppopupmenuHierarchy->
spmenu,
MFUNDERLINE);
02258 }
02259
02260 ppopupmenuHierarchy->
fAboutToHide =
FALSE;
02261
02262
02263
02264
02265
ThreadLock(pwndHierarchy, &tlpwndHierarchy);
02266 sizeHierarchy = (LONG)
xxxSendMessage(pwndHierarchy, MN_SIZEWINDOW,
MNSW_SIZE, 0);
02267
02268
if (!sizeHierarchy) {
02269
02270
02271
02272 UserAssert(ppopupmenuHierarchy->
fDelayedFree);
02273
if (ppopupmenuHierarchy->
fDesktopMenu) {
02274
xxxMNDestroyHandler(ppopupmenuHierarchy);
02275
xxxCleanupDesktopMenu(pwndHierarchy, pdesk);
02276 }
02277
02278
if (
ThreadUnlock(&tlpwndHierarchy)) {
02279
if (!ppopupmenuHierarchy->
fDesktopMenu) {
02280
xxxDestroyWindow(pwndHierarchy);
02281 }
02282 }
02283
02284
Unlock(&ppopupmenu->
spwndNextPopup);
02285
goto Exit;
02286 }
02287
02288 cxPopup = LOWORD(sizeHierarchy) + 2*
SYSMET(CXFIXEDFRAME);
02289 cyPopup = HIWORD(sizeHierarchy) + 2*
SYSMET(CYFIXEDFRAME);
02290
02291 ppopupmenu->
fHierarchyDropped =
TRUE;
02292
02293
02294
02295
02296
02297 ppopupmenuHierarchy->
iDropDir =
xxxMNPositionHierarchy(
02298 ppopupmenu, pItem, cxPopup, cyPopup, &xLeft, &yTop, &pMonitor);
02299
02300
if (ppopupmenu->
fIsMenuBar &&
_GetAsyncKeyState(VK_LBUTTON) & 0x8000) {
02301
02302
02303
02304
02305
02306 RECT rc;
02307 RECT rcParent;
02308
int xrightdrop;
02309
int xleftdrop;
02310
02311
02312
02313
02314
CopyOffsetRect(
02315 &rc,
02316 &pwndHierarchy->
rcWindow,
02317 xLeft - pwndHierarchy->
rcWindow.left,
02318 yTop - pwndHierarchy->
rcWindow.top);
02319
02320
02321
02322
02323 rcParent.left = pItem->
xItem + ppopupmenu->
spwndPopupMenu->
rcWindow.left;
02324 rcParent.top = pItem->
yItem + ppopupmenu->
spwndPopupMenu->
rcWindow.top;
02325 rcParent.right = rcParent.left + pItem->
cxItem;
02326 rcParent.bottom = rcParent.top + pItem->
cyItem;
02327
02328
if (
IntersectRect(&rc, &rc, &rcParent)) {
02329
02330
02331
02332
02333
02334
02335
02336
02337 xrightdrop = ppopupmenu->
spwndPopupMenu->
rcWindow.left +
02338 pItem->
xItem + pItem->
cxItem + cxPopup;
02339
02340
if (xrightdrop > pMonitor->
rcMonitor.right) {
02341 xrightdrop = 0;
02342 }
02343
02344 xleftdrop = ppopupmenu->
spwndPopupMenu->
rcWindow.left +
02345 pItem->
xItem - cxPopup;
02346
02347
if (xleftdrop < pMonitor->
rcMonitor.left) {
02348 xleftdrop = 0;
02349 }
02350
02351
if (((
SYSMET(MENUDROPALIGNMENT) ||
TestMFT(pItem, MFT_RIGHTORDER))
02352 && xleftdrop) || !xrightdrop) {
02353 xLeft = ppopupmenu->
spwndPopupMenu->
rcWindow.left +
02354 pItem->
xItem - cxPopup;
02355 ppopupmenuHierarchy->
iDropDir =
PAS_LEFT;
02356 }
else if (xrightdrop) {
02357 xLeft = ppopupmenu->
spwndPopupMenu->
rcWindow.left +
02358 pItem->
xItem + pItem->
cxItem;
02359 ppopupmenuHierarchy->
iDropDir =
PAS_RIGHT;
02360 }
02361 }
02362 }
02363
02364
02365
02366
02367
02368
if (ppopupmenu->
fIsMenuBar) {
02369
02370
02371
02372
02373
if (!ppopupmenu->
fDropNextPopup) {
02374 ppopupmenuHierarchy->
iDropDir |=
PAS_OUT;
02375 }
02376
02377
02378
02379
02380
if (ppopupmenu->
fDroppedLeft || (ppopupmenuHierarchy->
iDropDir ==
PAS_LEFT)) {
02381 ppopupmenuHierarchy->
fDroppedLeft =
TRUE;
02382 }
02383
02384
02385
02386
02387 ppopupmenu->
fDropNextPopup =
TRUE;
02388 }
else {
02389
02390
02391
02392 ppopupmenuHierarchy->
iDropDir |=
PAS_OUT;
02393
02394
02395
02396
02397
if (ppopupmenuHierarchy->
iDropDir ==
PAS_LEFT) {
02398 ppopupmenuHierarchy->
fDroppedLeft =
TRUE;
02399 }
02400 }
02401
02402
02403
02404
02405 UserAssert((ppopupmenu->
ppopupmenuRoot->
spwndActivePopup ==
NULL)
02406 ||
TestWF(ppopupmenu->
ppopupmenuRoot->
spwndActivePopup,
WFVISIBLE));
02407
02408
02409
02410
02411
Lock(&(ppopupmenu->
ppopupmenuRoot->
spwndActivePopup), pwndHierarchy);
02412
02413
02414
02415
02416
02417
if (ppopupmenuHierarchy->
spwndNotify !=
NULL) {
02418
ThreadLockAlways(ppopupmenuHierarchy->
spwndNotify, &tlpwndT);
02419
xxxUpdateWindow(ppopupmenuHierarchy->
spwndNotify);
02420
ThreadUnlock(&tlpwndT);
02421 }
02422
02423
02424
02425
02426
02427
if (pMenuState->
fDragAndDrop) {
02428
if (!
NT_SUCCESS(
xxxClientRegisterDragDrop(
HW(pwndHierarchy)))) {
02429 RIPMSG1(RIP_ERROR,
"xxxMNOpenHierarchy: xxxClientRegisterDragDrop failed:%#p", pwndHierarchy);
02430 }
02431 }
02432
02433
02434
02435
02436
02437
PlayEventSound(
USER_SOUND_MENUPOPUP);
02438
02439
xxxSetWindowPos(pwndHierarchy,
02440 (pMenuState->
fModelessMenu ?
PWND_TOP :
PWND_TOPMOST),
02441 xLeft, yTop, 0, 0,
02442 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOOWNERZORDER
02443 | (pMenuState->
fModelessMenu ? 0 : SWP_NOACTIVATE));
02444
02445
if (
FWINABLE()) {
02446
xxxWindowEvent(EVENT_SYSTEM_MENUPOPUPSTART, pwndHierarchy, OBJID_CLIENT, INDEXID_CONTAINER, 0);
02447 }
02448
02449
02450
02451
02452
02453
02454
if (pMenuState->
mnFocus ==
KEYBDHOLD) {
02455
xxxSendMessage(pwndHierarchy, MN_SELECTITEM, 0, 0
L);
02456 }
02457
02458
02459
02460
02461
02462
xxxUpdateWindow(pwndHierarchy);
02463
02464 ret = pwndHierarchy;
02465
ThreadUnlock(&tlpwndHierarchy);
02466
02467 Exit:
02468
02469
02470
02471
02472
if (fSendUninit
02473 && (ppopupmenu->
spwndNotify !=
NULL)) {
02474
02475
ThreadLockAlways(ppopupmenu->
spwndNotify, &tlpwndT);
02476
xxxSendMessage(ppopupmenu->
spwndNotify, WM_UNINITMENUPOPUP,
02477 (WPARAM)hmenuInit,
02478 MAKELONG(0, (ppopupmenu->
fIsSysMenu ? MF_SYSMENU : 0)));
02479
ThreadUnlock(&tlpwndT);
02480 }
02481
02482
return ret;
02483 }
02484
02485
02486
02487
02488
02489
02490
02491
02492 BOOL xxxMNHideNextHierarchy(
PPOPUPMENU ppopup)
02493 {
02494
if (ppopup->
spwndNextPopup !=
NULL) {
02495
TL tlpwndT;
02496
02497
ThreadLockAlways(ppopup->
spwndNextPopup, &tlpwndT);
02498
if (ppopup->
spwndNextPopup != ppopup->
spwndActivePopup)
02499
xxxSendMessage(ppopup->
spwndNextPopup, MN_CLOSEHIERARCHY, 0, 0
L);
02500
02501
xxxSendMessage(ppopup->
spwndNextPopup, MN_SELECTITEM, (WPARAM)-1, 0
L);
02502
ThreadUnlock(&tlpwndT);
02503
return TRUE;
02504 }
02505
return FALSE;
02506 }
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517 void xxxMNCloseHierarchy(
02518
PPOPUPMENU ppopupmenu,
PMENUSTATE pMenuState)
02519 {
02520
TL tlpwndNext;
02521
TL tlpwnd;
02522
TL tlpopup;
02523
PTHREADINFO ptiCurrent =
PtiCurrent();
02524
PDESKTOP pdesk;
02525
PWND pwndNext;
02526
02527
Validateppopupmenu(ppopupmenu);
02528
02529
02530
02531
02532
MNAnimate(pMenuState,
FALSE);
02533
02534
02535
02536
02537
02538
if (!ppopupmenu->
fHierarchyDropped) {
02539
02540
02541
02542 UserAssert(ppopupmenu->
spwndNextPopup ==
NULL);
02543
return;
02544 }
02545
02546
if (ppopupmenu->
fHideTimer)
02547 {
02548
_KillTimer(ppopupmenu->
spwndPopupMenu,
IDSYS_MNHIDE);
02549 ppopupmenu->
fHideTimer =
FALSE;
02550 }
02551
02552 pwndNext = ppopupmenu->
spwndNextPopup;
02553
if (pwndNext !=
NULL) {
02554
02555
ThreadLockAlways(pwndNext, &tlpwndNext);
02556
xxxSendMessage(pwndNext, MN_CLOSEHIERARCHY, 0, 0);
02557
02558
02559
02560
02561
02562
02563
02564
if (pMenuState->
fModelessMenu
02565 && pMenuState->
fInsideMenuLoop
02566 && !ppopupmenu->
fIsMenuBar) {
02567
02568
ThreadLockAlways(ppopupmenu->
spwndPopupMenu, &tlpwnd);
02569
xxxActivateThisWindow(ppopupmenu->
spwndPopupMenu, 0, 0);
02570
ThreadUnlock(&tlpwnd);
02571 }
02572
02573
if (
FWINABLE()) {
02574
xxxWindowEvent(EVENT_SYSTEM_MENUPOPUPEND, pwndNext, OBJID_CLIENT, INDEXID_CONTAINER, 0);
02575 }
02576
02577
02578
02579
02580
02581
02582 UserAssert(ptiCurrent->
pMenuState !=
NULL);
02583 pdesk = ptiCurrent->
rpdesk;
02584
02585
if (pwndNext == pdesk->
spwndMenu) {
02586
PPOPUPMENU ppopupmenuReal;
02587
02588 UserAssert(pdesk->
dwDTFlags &
DF_MENUINUSE);
02589
02590
02591
02592
02593
02594
xxxShowWindow(pwndNext, SW_HIDE |
TEST_PUDF(
PUDF_ANIMATE));
02595
02596
02597
02598
02599
02600
02601
02602
if (
TestWF(pwndNext,
WFVISIBLE)) {
02603
SetVisible(pwndNext,
SV_UNSET);
02604 }
02605
02606
#ifdef HAVE_MN_GETPPOPUPMENU
02607
ppopupmenuReal = (
PPOPUPMENU)
xxxSendMessage(pwndNext,
02608 MN_GETPPOPUPMENU,0, 0
L);
02609
#else
02610
ppopupmenuReal = ((
PMENUWND)pwndNext)->ppopupmenu;
02611
#endif
02612
UserAssert(ppopupmenuReal->
fDesktopMenu ==
TRUE);
02613
02614
02615
02616
02617
02618
if (pMenuState->
fDragAndDrop) {
02619
if (!
NT_SUCCESS(
xxxClientRevokeDragDrop(
HW(pwndNext)))) {
02620 RIPMSG1(RIP_ERROR,
"xxxMNCloseHierarchy: xxxClientRevokeRegisterDragDrop failed:%#p", pwndNext);
02621 }
02622 }
02623
02624
if (ppopupmenuReal !=
NULL) {
02625
xxxMNDestroyHandler(ppopupmenuReal);
02626
02627
02628
02629
02630
02631
02632 }
02633
02634
xxxCleanupDesktopMenu(pwndNext, pdesk);
02635
02636
ThreadUnlock(&tlpwndNext);
02637 }
else if (
ThreadUnlock(&tlpwndNext)) {
02638
02639
02640
02641
02642 UserAssert(pwndNext != pwndNext->
head.rpdesk->spwndMenu);
02643
xxxDestroyWindow(pwndNext);
02644 }
02645
02646
Unlock(&ppopupmenu->
spwndNextPopup);
02647 ppopupmenu->
fHierarchyDropped =
FALSE;
02648
02649 }
02650
02651
if (ppopupmenu->
fIsMenuBar) {
02652
Unlock(&ppopupmenu->
spwndActivePopup);
02653 }
else {
02654
Lock(&(ppopupmenu->
ppopupmenuRoot->
spwndActivePopup),
02655 ppopupmenu->
spwndPopupMenu);
02656 }
02657
02658
if (pMenuState->
fInsideMenuLoop &&
02659 (ppopupmenu->
posSelectedItem !=
MFMWFP_NOITEM)) {
02660
02661
02662
02663
02664
02665
PWND pwnd = ppopupmenu->
ppopupmenuRoot->
spwndNotify;
02666
if (pwnd) {
02667
ThreadLockAlways(pwnd, &tlpwnd);
02668
ThreadLockAlways(ppopupmenu->
spwndPopupMenu, &tlpopup);
02669
xxxSendMenuSelect(pwnd, ppopupmenu->
spwndPopupMenu,
02670 ppopupmenu->
spmenu, ppopupmenu->
posSelectedItem);
02671
ThreadUnlock(&tlpopup);
02672
ThreadUnlock(&tlpwnd);
02673 }
02674 }
02675
02676 }
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697 BOOL xxxMNDoubleClick(
PMENUSTATE pMenuState,
PPOPUPMENU ppopup,
int idxItem)
02698 {
02699
PMENU pMenu;
02700
PITEM pItem;
02701 MSG
msg;
02702
UINT uPos;
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
if (
xxxPeekMessage(&
msg,
NULL, 0, 0, PM_NOYIELD)) {
02716
if ((
msg.message == WM_LBUTTONUP) ||
02717 (
msg.message == WM_NCLBUTTONUP)) {
02718
xxxPeekMessage(&
msg,
NULL,
msg.message,
msg.message, PM_REMOVE);
02719 }
02720
#if DBG
02721
else if (
msg.message == WM_LBUTTONDBLCLK ||
02722
msg.message == WM_NCLBUTTONDBLCLK)
02723 {
02724 UserAssertMsg0(
FALSE,
"xxxMNDoubleClick found a double click");
02725 }
02726
#endif
02727
}
02728
02729
02730
02731
02732 pMenu = ppopup->
spmenu;
02733
if ((pMenu==
NULL) || ((
UINT)idxItem >= pMenu->
cItems)) {
02734
xxxMNDoScroll(ppopup, ppopup->
posSelectedItem,
FALSE);
02735
goto Done;
02736 }
02737
02738 pItem = pMenu->
rgItems + idxItem;
02739 uPos = idxItem;
02740
02741
02742
02743
02744
if (pItem->
fState & MFS_GRAYED)
02745
goto Done;
02746
02747
02748
02749
02750
do
02751 {
02752
if (pItem->
spSubMenu !=
NULL) {
02753
02754
02755
02756 pMenu = pItem->
spSubMenu;
02757 idxItem = (
UINT)
_GetMenuDefaultItem(pMenu, MF_BYPOSITION, 0);
02758
02759
if (idxItem != -1) {
02760 pItem = pMenu->
rgItems + idxItem;
02761 uPos = idxItem;
02762
continue;
02763 }
else
02764
break;
02765 }
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
if (!
TestWF(ppopup->
ppopupmenuRoot->
spwndNotify,
WFWIN40COMPAT))
02784 {
02785
TL tlpwndNotify, tlpopup;
02786
02787
ThreadLock(ppopup->
ppopupmenuRoot->
spwndNotify, &tlpwndNotify);
02788
ThreadLock(ppopup->
spwndPopupMenu, &tlpopup);
02789
xxxSendMenuSelect(ppopup->
ppopupmenuRoot->
spwndNotify,
02790 ppopup->
spwndPopupMenu, pMenu, idxItem);
02791
ThreadUnlock(&tlpopup);
02792
ThreadUnlock(&tlpwndNotify);
02793 }
02794
02795
xxxMNDismissWithNotify(pMenuState, pMenu, pItem, uPos, 0);
02796
return TRUE;
02797 }
02798
while (
TRUE);
02799
02800 Done:
02801
return(
FALSE);
02802 }
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818 PITEM xxxMNSelectItem(
02819
PPOPUPMENU ppopupmenu,
02820
PMENUSTATE pMenuState,
02821 UINT itemPos)
02822 {
02823
PITEM pItem =
NULL;
02824
TL tlpwndNotify;
02825
TL tlpwndPopup;
02826
TL tlpmenu;
02827
PWND pwndNotify;
02828
PMENU pmenu;
02829
02830
if (ppopupmenu->
posSelectedItem == itemPos) {
02831
02832
02833
02834
02835
if ((itemPos !=
MFMWFP_NOITEM) && (itemPos < ppopupmenu->
spmenu->
cItems)) {
02836
return &(ppopupmenu->
spmenu->
rgItems[itemPos]);
02837 }
02838
return NULL;
02839 }
02840
02841
02842
02843
02844
MNAnimate(pMenuState,
FALSE);
02845
02846
if (ppopupmenu->
fShowTimer) {
02847
_KillTimer(ppopupmenu->
spwndPopupMenu,
IDSYS_MNSHOW);
02848 ppopupmenu->
fShowTimer =
FALSE;
02849 }
02850
02851
ThreadLock(pmenu = ppopupmenu->
spmenu, &tlpmenu);
02852
ThreadLock(pwndNotify = ppopupmenu->
spwndNotify, &tlpwndNotify);
02853
02854
if (ppopupmenu->
fAboutToHide)
02855 {
02856
PPOPUPMENU ppopupPrev = ((
PMENUWND)(ppopupmenu->
spwndPrevPopup))->ppopupmenu;
02857
02858
_KillTimer(ppopupPrev->
spwndPopupMenu,
IDSYS_MNHIDE);
02859 ppopupPrev->
fHideTimer =
FALSE;
02860
if (ppopupPrev->
fShowTimer)
02861 {
02862
_KillTimer(ppopupPrev->
spwndPopupMenu,
IDSYS_MNSHOW);
02863 ppopupPrev->
fShowTimer =
FALSE;
02864 }
02865
02866
if (ppopupPrev->
posSelectedItem != ppopupPrev->
posDropped)
02867 {
02868
TL tlpmenuPopupMenuPrev;
02869
ThreadLock(ppopupPrev->
spmenu, &tlpmenuPopupMenuPrev);
02870
if (ppopupPrev->
posSelectedItem !=
MFMWFP_NOITEM) {
02871
xxxMNInvertItem(ppopupPrev, ppopupPrev->
spmenu,
02872 ppopupPrev->
posSelectedItem, ppopupPrev->
spwndNotify,
FALSE);
02873 }
02874
02875 ppopupPrev->
posSelectedItem = ppopupPrev->
posDropped;
02876
02877
xxxMNInvertItem(ppopupPrev, ppopupPrev->
spmenu,
02878 ppopupPrev->
posDropped, ppopupPrev->
spwndNotify,
TRUE);
02879
ThreadUnlock(&tlpmenuPopupMenuPrev);
02880 }
02881
02882 ppopupmenu->
fAboutToHide =
FALSE;
02883
Lock(&ppopupmenu->
ppopupmenuRoot->
spwndActivePopup, ppopupmenu->
spwndPopupMenu);
02884 }
02885
02886
if (
MNIsItemSelected(ppopupmenu)) {
02887
02888
02889
02890
if (ppopupmenu->
spwndNextPopup) {
02891
if (ppopupmenu->
fIsMenuBar) {
02892
xxxMNCloseHierarchy(ppopupmenu, pMenuState);
02893 }
else {
02894
MNSetTimerToCloseHierarchy(ppopupmenu);
02895 }
02896 }
02897
02898
goto DeselectItem;
02899 }
else if (
MNIsScrollArrowSelected(ppopupmenu)) {
02900
_KillTimer(ppopupmenu->
spwndPopupMenu, ppopupmenu->
posSelectedItem);
02901 DeselectItem:
02902
02903
xxxMNInvertItem(ppopupmenu, pmenu,
02904 ppopupmenu->
posSelectedItem, pwndNotify,
FALSE);
02905 }
02906
02907 ppopupmenu->
posSelectedItem = itemPos;
02908
02909
if (itemPos !=
MFMWFP_NOITEM) {
02910
02911
02912
02913
02914 pMenuState->
fAboutToAutoDismiss =
02915 pMenuState->
fMouseOffMenu =
FALSE;
02916
02917
if (pMenuState->
fButtonDown) {
02918
xxxMNDoScroll(ppopupmenu, itemPos,
TRUE);
02919 }
02920
02921 pItem =
xxxMNInvertItem(ppopupmenu, pmenu,
02922 itemPos, pwndNotify,
TRUE);
02923
ThreadUnlock(&tlpwndNotify);
02924
ThreadUnlock(&tlpmenu);
02925
return pItem;
02926
02927 }
else if (
FWINABLE()) {
02928
02929
02930
02931
xxxWindowEvent(EVENT_OBJECT_FOCUS, ppopupmenu->
spwndPopupMenu,
02932 ((ppopupmenu->
spwndNotify != ppopupmenu->
spwndPopupMenu) ? OBJID_CLIENT :
02933 (ppopupmenu->
fIsSysMenu ? OBJID_SYSMENU : OBJID_MENU)), 0, 0);
02934 }
02935
02936
ThreadUnlock(&tlpwndNotify);
02937
ThreadUnlock(&tlpmenu);
02938
02939
if (ppopupmenu->
spwndPrevPopup !=
NULL) {
02940
PPOPUPMENU pp;
02941
02942
02943
02944
02945
02946
if (ppopupmenu->
fHasMenuBar && (ppopupmenu->
spwndPrevPopup ==
02947 ppopupmenu->
spwndNotify)) {
02948 pp = ppopupmenu->
ppopupmenuRoot;
02949 }
else {
02950
#ifdef HAVE_MN_GETPPOPUPMENU
02951
TL tlpwndPrevPopup;
02952
ThreadLock(ppopupmenu->
spwndPrevPopup, &tlpwndPrevPopup);
02953 pp = (
PPOPUPMENU)
xxxSendMessage(ppopupmenu->
spwndPrevPopup,
02954 MN_GETPPOPUPMENU, 0, 0
L);
02955
ThreadUnlock(&tlpwndPrevPopup);
02956
#else
02957
pp = ((
PMENUWND)ppopupmenu->
spwndPrevPopup)->ppopupmenu;
02958
#endif
02959
}
02960
02961
02962
02963
02964
02965
ThreadLock(pp->
spwndNotify, &tlpwndNotify);
02966
ThreadLock(pp->
spwndPopupMenu, &tlpwndPopup);
02967
xxxSendMenuSelect(pp->
spwndNotify, pp->
spwndPopupMenu, pp->
spmenu, pp->
posSelectedItem);
02968
ThreadUnlock(&tlpwndPopup);
02969
ThreadUnlock(&tlpwndNotify);
02970 }
02971
02972
return NULL;
02973 }
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983 UINT MNItemHitTest(
PMENU pMenu,
PWND pwnd, POINT pt)
02984 {
02985
PITEM pItem;
02986
UINT iItem;
02987 RECT rect;
02988
02989
PTHREADINFO ptiCurrent =
PtiCurrent();
02990
02991
if (pMenu->
cItems == 0)
02992
return MFMWFP_NOITEM;
02993
02994
02995
02996
02997
02998
02999
if (
TestMF(pMenu,
MFISPOPUP)) {
03000
03001
03002
03003
03004
CopyInflateRect(&rect, &(pwnd->
rcWindow),
03005 -
SYSMET(CXFIXEDFRAME), -
SYSMET(CYFIXEDFRAME));
03006
03007
if (!
PtInRect(&rect, pt)) {
03008
return MFMWFP_NOITEM;
03009 }
03010
03011
03012
#ifdef USE_MIRRORING
03013
if (
TestWF(pwnd, WEFLAYOUTRTL)) {
03014 pt.x = pwnd->
rcClient.right - pt.x;
03015 }
else
03016
#endif
03017
{
03018 pt.x -= pwnd->
rcClient.left;
03019 }
03020 pt.y -= pwnd->
rcClient.top;
03021
03022
03023
03024
03025
if (pt.y < 0) {
03026
return MFMWFP_UPARROW;
03027 }
else if (pt.y > (
int)pMenu->
cyMenu) {
03028
return MFMWFP_DOWNARROW;
03029 }
03030
03031 }
else {
03032
03033
#ifdef USE_MIRRORING
03034
if (
TestWF(pwnd, WEFLAYOUTRTL) &&
03035 (
03036 (ptiCurrent->
pq->
codeCapture ==
SCREEN_CAPTURE) || (ptiCurrent->
pq->
codeCapture ==
NO_CAP_SYS)
03037 )
03038 ) {
03039 pt.x = pwnd->
rcWindow.right - pt.x;
03040 }
else
03041
#endif
03042
{
03043 pt.x -= pwnd->
rcWindow.left;
03044 }
03045 pt.y -= pwnd->
rcWindow.top;
03046 }
03047
03048
03049
03050
03051
03052
if (pMenu->
dwArrowsOn !=
MSA_OFF) {
03053 UserAssert(
TestMF(pMenu,
MFISPOPUP));
03054 pItem =
MNGetToppItem(pMenu);
03055 rect.left = rect.top = 0;
03056 rect.right = pItem->
cxItem;
03057 rect.bottom = pItem->
cyItem;
03058
for (iItem = pMenu->
iTop; (iItem < (
int)pMenu->
cItems) && (rect.top < (
int)pMenu->
cyMenu); iItem++) {
03059
03060
if (
PtInRect(&rect, pt)) {
03061
return iItem;
03062 }
03063
03064 pItem++;
03065 rect.top = rect.bottom;
03066 rect.bottom += pItem->
cyItem;
03067 }
03068 }
else {
03069
03070
03071
03072
for (iItem = 0, pItem = pMenu->
rgItems; iItem < pMenu->
cItems; iItem++, pItem++) {
03073
03074 rect.left = pItem->xItem;
03075 rect.top = pItem->yItem;
03076 rect.right = pItem->xItem + pItem->cxItem;
03077 rect.bottom = pItem->yItem + pItem->cyItem;
03078
03079
if (
PtInRect(&rect, pt)) {
03080
return(iItem);
03081 }
03082 }
03083 }
03084
03085
03086
return(
MFMWFP_NOITEM);
03087 }
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097 void LockMFMWFPWindow (PULONG_PTR puHitArea, ULONG_PTR uNewHitArea)
03098 {
03099
03100
03101
03102
if (*puHitArea == uNewHitArea) {
03103
return;
03104 }
03105
03106
03107
03108
03109
UnlockMFMWFPWindow(puHitArea);
03110
03111
03112
03113
03114
if (
IsMFMWFPWindow(uNewHitArea)) {
03115
Lock(puHitArea, (
PWND)uNewHitArea);
03116 }
else {
03117 *puHitArea = uNewHitArea;
03118 }
03119 }
03120
03121
03122
03123
03124
03125
03126
03127
03128 void UnlockMFMWFPWindow (PULONG_PTR puHitArea)
03129 {
03130
if (
IsMFMWFPWindow(*puHitArea)) {
03131
Unlock(puHitArea);
03132 }
else {
03133 *puHitArea =
MFMWFP_OFFMENU;
03134 }
03135 }
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145 BOOL IsMFMWFPWindow (ULONG_PTR uHitArea)
03146 {
03147
switch(uHitArea) {
03148
case MFMWFP_OFFMENU:
03149
case MFMWFP_NOITEM:
03150
case MFMWFP_ALTMENU:
03151
return FALSE;
03152
03153
default:
03154
return TRUE;
03155 }
03156 }
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180 LONG_PTR
xxxMNFindWindowFromPoint(
03181
PPOPUPMENU ppopupmenu,
03182 PUINT pIndex,
03183 POINTS screenPt)
03184 {
03185 POINT pt;
03186 RECT rect;
03187 LONG_PTR longHit;
03188
UINT itemHit;
03189
PWND pwnd;
03190
TL tlpwndT;
03191
#ifdef USE_MIRRORING
03192
int cx;
03193
#endif
03194
03195
03196 *pIndex = 0;
03197
03198
if (ppopupmenu->
spwndNextPopup) {
03199
03200
03201
03202
03203
03204
ThreadLockAlways(ppopupmenu->
spwndNextPopup, &tlpwndT);
03205 longHit =
xxxSendMessage(ppopupmenu->
spwndNextPopup,
03206 MN_FINDMENUWINDOWFROMPOINT, (WPARAM)&itemHit,
03207 MAKELONG(screenPt.x, screenPt.y));
03208
ThreadUnlock(&tlpwndT);
03209
03210
03211
03212
03213
if (
IsMFMWFPWindow(longHit)) {
03214 longHit = (LONG_PTR)
RevalidateHwnd((HWND)longHit);
03215 }
03216
03217
if (longHit) {
03218
03219
03220
03221
03222
03223 *pIndex = itemHit;
03224
return longHit;
03225 }
03226 }
03227
03228
if (ppopupmenu->
fIsMenuBar) {
03229
int cBorders;
03230
03231
03232
03233
03234 pwnd = ppopupmenu->
spwndNotify;
03235
if (pwnd ==
NULL) {
03236
return MFMWFP_OFFMENU;
03237 }
03238
03239 pt.x = screenPt.x;
03240 pt.y = screenPt.y;
03241
03242
if (ppopupmenu->
fIsSysMenu) {
03243
03244
if (!
_HasCaptionIcon(pwnd)) {
03245
03246
03247
03248
return(0
L);
03249 }
03250
03251
03252
03253
03254
if (
TestWF(pwnd,
WFMINIMIZED)) {
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
if (
PtInRect(&(pwnd->
rcWindow), pt)) {
03274
return MFMWFP_NOITEM;
03275 }
03276
03277
03278
03279
03280
return MFMWFP_OFFMENU;
03281 }
03282
03283
03284
03285
03286
03287 rect.top = rect.left = 0;
03288 rect.right =
SYSMET(CXSIZE);
03289 rect.bottom =
SYSMET(CYSIZE);
03290
03291 cBorders =
GetWindowBorders(pwnd->style, pwnd->ExStyle,
TRUE,
FALSE);
03292
03293
OffsetRect(&rect, pwnd->
rcWindow.left + cBorders*
SYSMET(CXBORDER),
03294 pwnd->
rcWindow.top + cBorders*
SYSMET(CYBORDER));
03295
#ifdef USE_MIRRORING
03296
03297
if (
TestWF(pwnd, WEFLAYOUTRTL)) {
03298 cx = rect.right - rect.left;
03299 rect.right = pwnd->
rcWindow.right - (rect.left - pwnd->
rcWindow.left);
03300 rect.left = rect.right - cx;
03301 }
03302
#endif
03303
if (
PtInRect(&rect, pt)) {
03304 *pIndex = 0;
03305
return(
MFMWFP_NOITEM);
03306 }
03307
03308
03309
03310
if (ppopupmenu->
spmenuAlternate) {
03311 itemHit =
MNItemHitTest(ppopupmenu->
spmenuAlternate, pwnd, pt);
03312
if (itemHit !=
MFMWFP_NOITEM) {
03313 *pIndex = itemHit;
03314
return MFMWFP_ALTMENU;
03315 }
03316 }
03317
return MFMWFP_OFFMENU;
03318 }
else {
03319
if (
TestWF(ppopupmenu->
spwndNotify,
WFMINIMIZED)) {
03320
03321
03322
03323
03324
return MFMWFP_OFFMENU;
03325 }
03326 }
03327 }
else {
03328 pwnd = ppopupmenu->
spwndPopupMenu;
03329
03330
03331
03332
03333
03334 pt.x = screenPt.x;
03335 pt.y = screenPt.y;
03336
if (!
PtInRect(&pwnd->
rcWindow, pt)) {
03337
03338
03339
03340
03341
return MFMWFP_OFFMENU;
03342 }
03343 }
03344
03345 pt.x = screenPt.x;
03346 pt.y = screenPt.y;
03347
03348 itemHit =
MNItemHitTest(ppopupmenu->
spmenu, pwnd, pt);
03349
03350
if (ppopupmenu->
fIsMenuBar) {
03351
03352
03353
03354
03355
03356
if (itemHit ==
MFMWFP_NOITEM) {
03357
03358
03359
03360
03361
if (ppopupmenu->
spmenuAlternate) {
03362 itemHit =
MNItemHitTest(ppopupmenu->
spmenuAlternate, pwnd, pt);
03363
if (itemHit !=
MFMWFP_NOITEM) {
03364 *pIndex = itemHit;
03365
return MFMWFP_ALTMENU;
03366 }
03367 }
03368
return MFMWFP_OFFMENU;
03369 }
03370
03371 *pIndex = itemHit;
03372
return MFMWFP_NOITEM;
03373 }
else {
03374
03375
03376
03377
03378
03379 *pIndex = itemHit;
03380
return (LONG_PTR)pwnd;
03381 }
03382
return MFMWFP_OFFMENU;
03383 }
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395 void xxxMNCancel(
03396
PMENUSTATE pMenuState,
03397 UINT uMsg,
03398 UINT cmd,
03399 LPARAM lParam)
03400 {
03401
PPOPUPMENU ppopupmenu = pMenuState->
pGlobalPopupMenu;
03402
BOOL fSynchronous = ppopupmenu->
fSynchronous;
03403
BOOL fTrackFlagsSet = ppopupmenu->
fIsTrackPopup;
03404
BOOL fIsSysMenu = ppopupmenu->
fIsSysMenu;
03405
BOOL fIsMenuBar = ppopupmenu->
fIsMenuBar;
03406
BOOL fNotify = !ppopupmenu->
fNoNotify;
03407
PWND pwndT;
03408
TL tlpwndT;
03409
TL tlpwndPopupMenu;
03410
03411
Validateppopupmenu(ppopupmenu);
03412
03413 pMenuState->
fInsideMenuLoop =
FALSE;
03414 pMenuState->
fButtonDown =
FALSE;
03415
03416
03417
03418
03419
03420 ppopupmenu->
fDestroyed =
TRUE;
03421
03422
03423
03424
03425
if (
PtiCurrent() != pMenuState->
ptiMenuStateOwner) {
03426 RIPMSG1(RIP_WARNING,
"xxxMNCancel: Thread %#p doesn't own the menu loop",
PtiCurrent());
03427
return;
03428 }
03429
03430
03431
03432
03433
03434
03435
if (ppopupmenu->
fInCancel) {
03436 RIPMSG1(RIP_WARNING,
"xxxMNCancel: already in cancel. ppopupmenu:%#p", ppopupmenu);
03437
return;
03438 }
03439 ppopupmenu->
fInCancel =
TRUE;
03440
03441
ThreadLock(ppopupmenu->
spwndPopupMenu, &tlpwndPopupMenu);
03442
03443
03444
03445
03446
xxxMNCloseHierarchy(ppopupmenu, pMenuState);
03447
03448
03449
03450
03451
xxxMNSelectItem(ppopupmenu, pMenuState,
MFMWFP_NOITEM);
03452
03453 pMenuState->
fMenuStarted =
FALSE;
03454
03455 pwndT = ppopupmenu->
spwndNotify;
03456
03457
ThreadLock(pwndT, &tlpwndT);
03458
03459
xxxMNReleaseCapture();
03460
03461
if (fTrackFlagsSet) {
03462
03463
03464
03465
if (
FWINABLE()) {
03466
xxxWindowEvent(EVENT_SYSTEM_MENUPOPUPEND,
03467 ppopupmenu->
spwndPopupMenu, OBJID_CLIENT, 0, 0);
03468 }
03469
03470 UserAssert(ppopupmenu->
spwndPopupMenu != ppopupmenu->
spwndPopupMenu->
head.rpdesk->spwndMenu);
03471
xxxDestroyWindow(ppopupmenu->
spwndPopupMenu);
03472 }
03473
03474
if (pwndT ==
NULL) {
03475
ThreadUnlock(&tlpwndT);
03476
ThreadUnlock(&tlpwndPopupMenu);
03477
return;
03478 }
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
xxxSendMenuSelect(pwndT,
NULL,
SMS_NOMENU,
MFMWFP_NOITEM);
03489
03490
if (
FWINABLE()) {
03491
xxxWindowEvent(EVENT_SYSTEM_MENUEND, pwndT, (fIsSysMenu ?
03492 OBJID_SYSMENU : (fIsMenuBar ? OBJID_MENU : OBJID_WINDOW)),
03493 INDEXID_CONTAINER, 0);
03494 }
03495
03496
if (fNotify) {
03497
03498
03499
03500
03501
xxxSendMessage(pwndT, WM_EXITMENULOOP,
03502 ((fTrackFlagsSet && !fIsSysMenu)? 1 : 0), 0);
03503 }
03504
03505
if (uMsg != 0) {
03506
PlayEventSound(
USER_SOUND_MENUCOMMAND);
03507 pMenuState->
cmdLast = cmd;
03508
if (!fSynchronous) {
03509
if (!fIsSysMenu && fTrackFlagsSet && !
TestWF(pwndT,
WFWIN31COMPAT)) {
03510
xxxSendMessage(pwndT, uMsg, cmd, lParam);
03511 }
else {
03512
_PostMessage(pwndT, uMsg, cmd, lParam);
03513 }
03514 }
03515 }
else
03516 pMenuState->
cmdLast = 0;
03517
03518
ThreadUnlock(&tlpwndT);
03519
03520
ThreadUnlock(&tlpwndPopupMenu);
03521
03522 }
03523
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533 void xxxMNButtonDown(
03534
PPOPUPMENU ppopupmenu,
03535
PMENUSTATE pMenuState,
03536 UINT posItemHit, BOOL fClick)
03537 {
03538
PITEM pItem;
03539
BOOL fOpenHierarchy;
03540
03541
03542
03543
03544
03545
if (ppopupmenu->
posSelectedItem != posItemHit) {
03546
03547
03548
03549
03550
03551
if (fClick) {
03552 fOpenHierarchy =
TRUE;
03553 ppopupmenu->
fToggle =
FALSE;
03554 }
03555
else
03556 {
03557 fOpenHierarchy = (ppopupmenu->
fDropNextPopup != 0);
03558 }
03559
03560
03561
03562
03563
03564
03565
03566 pItem =
xxxMNSelectItem(ppopupmenu, pMenuState, posItemHit);
03567
if (
MNIsPopupItem(pItem) && fOpenHierarchy) {
03568
03569
if (
xxxMNOpenHierarchy(ppopupmenu, pMenuState) == (
PWND)-1) {
03570
return;
03571 }
03572 }
03573 }
else {
03574
03575
03576
03577
03578
03579
03580
if (fClick) {
03581 ppopupmenu->
fToggle =
TRUE;
03582 }
03583
03584
if (!
xxxMNHideNextHierarchy(ppopupmenu) && fClick &&
xxxMNOpenHierarchy(ppopupmenu, pMenuState))
03585 ppopupmenu->
fToggle =
FALSE;
03586 }
03587
03588
if (fClick) {
03589 pMenuState->
fButtonDown =
TRUE;
03590
xxxMNDoScroll(ppopupmenu, posItemHit,
TRUE);
03591 }
03592 }
03593
03594
03595
03596
03597
03598
03599
03600 void MNSetTimerToAutoDismiss(
PMENUSTATE pMenuState,
PWND pwnd)
03601 {
03602
if (pMenuState->
fAutoDismiss && !pMenuState->
fAboutToAutoDismiss) {
03603
if (
_SetTimer(pwnd,
IDSYS_MNAUTODISMISS, 16 *
gdtMNDropDown,
NULL)) {
03604 pMenuState->
fAboutToAutoDismiss =
TRUE;
03605 }
else {
03606 RIPMSG0(RIP_WARNING,
"xxxMNMouseMove: Failed to set autodismiss timer");
03607 }
03608 }
03609 }
03610
03611
03612
03613
03614
03615
03616
03617
03618 void xxxMNMouseMove(
03619
PPOPUPMENU ppopup,
03620
PMENUSTATE pMenuState,
03621 POINTS ptScreen)
03622 {
03623 LONG_PTR cmdHitArea;
03624
UINT uFlags;
03625
UINT cmdItem;
03626
PWND pwnd;
03627
TL tlpwndT;
03628
03629
03630
if (!
IsRootPopupMenu(ppopup)) {
03631 RIPMSG0(RIP_ERROR,
03632
"MenuMouseMoveHandler() called for a non top most menu");
03633
return;
03634 }
03635
03636
03637
03638
03639
03640
03641
if ((ptScreen.x == pMenuState->
ptMouseLast.x) && (ptScreen.y == pMenuState->
ptMouseLast.y))
03642
return;
03643
03644 pMenuState->
ptMouseLast.x = ptScreen.x;
03645 pMenuState->
ptMouseLast.y = ptScreen.y;
03646
03647
03648
03649
03650 cmdHitArea =
xxxMNFindWindowFromPoint(ppopup, &cmdItem, ptScreen);
03651
03652
03653
03654
03655
if (pMenuState->
fInDoDragDrop) {
03656
xxxMNUpdateDraggingInfo(pMenuState, cmdHitArea, cmdItem);
03657 }
03658
03659
if (pMenuState->
mnFocus ==
KEYBDHOLD) {
03660
03661
03662
03663
03664
03665
if ((cmdHitArea ==
MFMWFP_OFFMENU) ||
03666 ((cmdHitArea ==
MFMWFP_NOITEM) &&
TestWF(ppopup->
spwndNotify,
WFMINIMIZED))) {
03667
return;
03668 }
03669
03670 pMenuState->
mnFocus =
MOUSEHOLD;
03671 }
03672
03673
if (cmdHitArea ==
MFMWFP_ALTMENU) {
03674
03675
03676
03677
03678
03679
03680
03681
if (pMenuState->
fButtonDown) {
03682
xxxMNSwitchToAlternateMenu(ppopup);
03683 cmdHitArea =
MFMWFP_NOITEM;
03684 }
else
03685
goto OverNothing;
03686 }
03687
03688
if (cmdHitArea ==
MFMWFP_NOITEM) {
03689
03690
03691
03692
03693
03694
03695
03696
03697
xxxMNButtonDown(ppopup, pMenuState, cmdItem,
FALSE);
03698
return;
03699 }
else if (cmdHitArea != 0) {
03700
03701 pwnd = (
PWND)(cmdHitArea);
03702
ThreadLock(pwnd, &tlpwndT);
03703
03704 UserAssert(
TestWF(pwnd,
WFVISIBLE));
03705
03706
03707
03708
03709
03710 ppopup = ((
PMENUWND)pwnd)->ppopupmenu;
03711
if (pMenuState->
fModelessMenu
03712 && !pMenuState->
fInDoDragDrop
03713 && !ppopup->
fTrackMouseEvent) {
03714
03715 TRACKMOUSEEVENT tme;
03716
03717
03718 tme.dwFlags = TME_LEAVE;
03719 tme.hwndTrack =
PtoH(pwnd);
03720
TrackMouseEvent(&tme);
03721 ppopup->
fTrackMouseEvent =
TRUE;
03722
03723
03724
03725
03726
03727
xxxSendMessage(pwnd, WM_SETCURSOR, (WPARAM)
HWq(pwnd), MAKELONG(MSGF_MENU, 0));
03728
03729 }
03730
03731
03732
03733
03734 uFlags = (
UINT)
xxxSendMessage(pwnd, MN_SELECTITEM, (WPARAM)cmdItem, 0
L);
03735
if ((uFlags & MF_POPUP) && !(uFlags & MFS_GRAYED)) {
03736
03737
03738
03739
03740
if (!
xxxSendMessage(pwnd, MN_SETTIMERTOOPENHIERARCHY, 0, 0
L)) {
03741
xxxMNHideNextHierarchy(ppopup);
03742 }
03743 }
03744
ThreadUnlock(&tlpwndT);
03745 }
else
03746 OverNothing:
03747 {
03748
03749
if (ppopup->
spwndActivePopup !=
NULL) {
03750 pwnd = ppopup->
spwndActivePopup;
03751
03752
ThreadLock(pwnd, &tlpwndT);
03753
xxxSendMessage(pwnd, MN_SELECTITEM,
MFMWFP_NOITEM, 0
L);
03754
MNSetTimerToAutoDismiss(pMenuState, pwnd);
03755
ThreadUnlock(&tlpwndT);
03756 }
else {
03757
xxxMNSelectItem(ppopup, pMenuState,
MFMWFP_NOITEM);
03758 }
03759
03760 }
03761 }
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772 void xxxMNButtonUp(
03773
PPOPUPMENU ppopup,
03774
PMENUSTATE pMenuState,
03775 UINT posItemHit,
03776 LPARAM lParam)
03777 {
03778
PITEM pItem;
03779
03780
if (!pMenuState->
fButtonDown) {
03781
03782
03783
03784
03785
return;
03786 }
03787
03788
if (posItemHit ==
MFMWFP_NOITEM) {
03789 RIPMSG0(RIP_WARNING,
"button up on no item");
03790
goto ExitButtonUp;
03791 }
03792
03793
if (ppopup->
posSelectedItem != posItemHit) {
03794
goto ExitButtonUp;
03795 }
03796
03797
if (ppopup->
fIsMenuBar) {
03798
03799
03800
03801
03802
if (ppopup->
fHierarchyDropped) {
03803
if (!ppopup->
fToggle) {
03804
goto ExitButtonUp;
03805 }
else {
03806
03807
03808
03809 ppopup->
fToggle =
FALSE;
03810
xxxMNDismiss(pMenuState);
03811
return;
03812 }
03813 }
03814 }
else if (ppopup->
fShowTimer) {
03815 ppopup->
fToggle =
FALSE;
03816
03817
03818
03819
03820
xxxMNOpenHierarchy(ppopup, pMenuState);
03821
03822
goto ExitButtonUp;
03823 }
03824
03825
03826
03827
03828
03829
if (ppopup->
posSelectedItem ==
MFMWFP_NOITEM)
03830
goto ExitButtonUp;
03831
03832
if (ppopup->
posSelectedItem >= ppopup->
spmenu->
cItems)
03833
goto ExitButtonUp;
03834
03835
03836
03837
03838 pItem = &(ppopup->
spmenu->
rgItems[ppopup->
posSelectedItem]);
03839
03840
03841
03842
03843
03844
03845
03846
03847
if (!(pItem->
fType & MFT_SEPARATOR)
03848 && !(pItem->
fState & MFS_GRAYED)
03849 && (pItem->
spSubMenu ==
NULL)) {
03850
03851
xxxMNDismissWithNotify(pMenuState, ppopup->
spmenu, pItem,
03852 ppopup->
posSelectedItem, lParam);
03853
return;
03854 }
03855
03856 ExitButtonUp:
03857 pMenuState->
fButtonDown =
03858 pMenuState->
fButtonAlwaysDown =
FALSE;
03859 }
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870 UINT MNSetTimerToOpenHierarchy(
03871
PPOPUPMENU ppopup)
03872 {
03873
PITEM pItem;
03874
03875
03876
03877
03878
if (ppopup->
posSelectedItem ==
MFMWFP_NOITEM)
03879
return(0);
03880
03881
if (ppopup->
posSelectedItem >= ppopup->
spmenu->
cItems)
03882
return(0);
03883
03884
03885
03886
03887
03888 pItem = ppopup->
spmenu->
rgItems + ppopup->
posSelectedItem;
03889
if ((pItem->
spSubMenu ==
NULL) || (pItem->
fState & MFS_GRAYED))
03890
return(0);
03891
03892
if (ppopup->
fShowTimer
03893 || (ppopup->
fHierarchyDropped
03894 && (ppopup->
posSelectedItem == ppopup->
posDropped))) {
03895
03896
03897
03898
03899
return 1;
03900 }
03901
03902
if (!
_SetTimer(ppopup->
spwndPopupMenu,
IDSYS_MNSHOW,
gdtMNDropDown,
NULL))
03903
return (
UINT)-1;
03904
03905 ppopup->
fShowTimer =
TRUE;
03906
03907
return 1;
03908 }
03909
03910
03911
03912
03913
03914
03915
03916
03917 UINT MNSetTimerToCloseHierarchy(
PPOPUPMENU ppopup)
03918 {
03919
03920
if (!ppopup->
fHierarchyDropped)
03921
return(0);
03922
03923
if (ppopup->
fHideTimer)
03924
return(1);
03925
03926
if (!
_SetTimer(ppopup->
spwndPopupMenu,
IDSYS_MNHIDE,
gdtMNDropDown,
NULL))
03927
return((
UINT) -1);
03928
03929 ppopup->
fHideTimer =
TRUE;
03930
03931 ppopup = ((
PMENUWND)(ppopup->
spwndNextPopup))->ppopupmenu;
03932 ppopup->
fAboutToHide =
TRUE;
03933
03934
return(1);
03935 }
03936
03937
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951 BOOL xxxCallHandleMenuMessages(
PMENUSTATE pMenuState,
PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam)
03952 {
03953
BOOL fHandled;
03954 MSG
msg;
03955
03956
CheckLock(pwnd);
03957
03958 UserAssert(pMenuState->
fModelessMenu || pMenuState->
fInDoDragDrop);
03959
03960
03961
03962
03963
03964
03965
03966
if (pMenuState->
fMouseOffMenu && pMenuState->
fButtonDown) {
03967 UserAssert(!pMenuState->
fInDoDragDrop && pMenuState->
fModelessMenu);
03968
MNCheckButtonDownState(pMenuState);
03969 }
03970
03971
03972
03973
03974
msg.hwnd =
HW(pwnd);
03975
msg.message = message;
03976
msg.wParam = wParam;
03977
03978
03979
03980
03981
if ((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST)) {
03982
msg.lParam = MAKELONG(
GET_X_LPARAM(lParam) + pwnd->
rcClient.left,
03983
GET_Y_LPARAM(lParam) + pwnd->
rcClient.top);
03984 }
else {
03985
msg.lParam = lParam;
03986 }
03987
03988
03989
03990
03991
msg.time = 0;
03992
msg.pt.x =
msg.pt.x = 0;
03993
03994
03995 UserAssert(pMenuState->
pGlobalPopupMenu !=
NULL);
03996
03997 pMenuState->
fInCallHandleMenuMessages =
TRUE;
03998 fHandled =
xxxHandleMenuMessages(&
msg, pMenuState, pMenuState->
pGlobalPopupMenu);
03999 pMenuState->
fInCallHandleMenuMessages =
FALSE;
04000
04001
04002
04003
04004
04005
if (fHandled
04006 && pMenuState->
fModelessMenu
04007 &&
ExitMenuLoop (pMenuState, pMenuState->
pGlobalPopupMenu)) {
04008
04009
xxxEndMenuLoop (pMenuState, pMenuState->
pGlobalPopupMenu);
04010
xxxMNEndMenuState(
TRUE);
04011 }
04012
04013
return fHandled;
04014 }
04015
04016
04017
04018
04019
04020
04021
04022 LRESULT
xxxMenuWindowProc(
04023
PWND pwnd,
04024 UINT message,
04025 WPARAM wParam,
04026 LPARAM lParam)
04027 {
04028
BOOL fIsRecursedMenu;
04029 LRESULT lRet;
04030 PAINTSTRUCT ps;
04031
PPOPUPMENU ppopupmenu;
04032
PMENUSTATE pMenuState;
04033
PMENU pmenu;
04034
PITEM pItem;
04035
TL tlpmenu;
04036
TL tlpwndNotify;
04037
PDESKTOP pdesk = pwnd->
head.rpdesk;
04038 POINT ptOrg;
04039 HDC hdcAni;
04040
04041
CheckLock(pwnd);
04042
04043
VALIDATECLASSANDSIZE(pwnd, message, wParam, lParam,
FNID_MENU, WM_NCCREATE);
04044
04045
04046
04047
04048
04049 pMenuState =
GetpMenuState(pwnd);
04050 ppopupmenu = ((
PMENUWND)pwnd)->ppopupmenu;
04051 pmenu = (ppopupmenu !=
NULL ? ppopupmenu->
spmenu :
NULL);
04052
if ((pMenuState ==
NULL) || (pmenu ==
NULL)) {
04053
switch (message) {
04054
case WM_NCCREATE:
04055
case WM_FINALDESTROY:
04056
break;
04057
04058
case MN_SETHMENU:
04059
if (ppopupmenu !=
NULL) {
04060
break;
04061 }
else {
04062
return 0;
04063 }
04064
04065
default:
04066
goto CallDWP;
04067 }
04068 }
else {
04069
04070
04071
04072 fIsRecursedMenu = ((ppopupmenu->
ppopupmenuRoot !=
NULL)
04073 &&
IsRecursedMenuState(pMenuState, ppopupmenu));
04074
if (fIsRecursedMenu) {
04075
while (
IsRecursedMenuState(pMenuState, ppopupmenu)
04076 && (pMenuState->
pmnsPrev !=
NULL)) {
04077 pMenuState = pMenuState->
pmnsPrev;
04078 }
04079 UserAssert(pMenuState->
pGlobalPopupMenu == ppopupmenu->
ppopupmenuRoot);
04080 }
04081
04082
Validateppopupmenu(ppopupmenu);
04083
04084
04085
04086
04087
04088
if (pMenuState->
fModelessMenu && !pMenuState->
fInCallHandleMenuMessages) {
04089
04090
04091
04092
04093
if (fIsRecursedMenu) {
04094
if (((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST))
04095 || ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST))
04096 || ((message >= WM_NCMOUSEFIRST) && (message <= WM_NCMOUSELAST))) {
04097
04098
goto CallDWP;
04099 }
04100 }
else {
04101
if (
xxxCallHandleMenuMessages(pMenuState, pwnd, message, wParam, lParam)) {
04102
return 0;
04103 }
04104 }
04105 }
04106 }
04107
04108
switch (message) {
04109
case WM_NCCREATE:
04110
04111
04112
04113
04114
if (((
PMENUWND)pwnd)->ppopupmenu !=
NULL) {
04115 RIPMSG1(RIP_ERROR,
"xxxMenuWindowProc: evil WM_NCCREATE. already initialized. pwnd:%p", pwnd);
04116
return FALSE;
04117 }
04118 ppopupmenu =
MNAllocPopup(
TRUE);
04119
if (ppopupmenu ==
NULL) {
04120
return FALSE;
04121 }
04122
04123 ((
PMENUWND)pwnd)->ppopupmenu = ppopupmenu;
04124 ppopupmenu->
posSelectedItem =
MFMWFP_NOITEM;
04125
Lock(&(ppopupmenu->
spwndPopupMenu), pwnd);
04126
return TRUE;
04127
04128
case WM_NCCALCSIZE:
04129
xxxDefWindowProc(pwnd, message, wParam, lParam);
04130
if (pmenu->
dwArrowsOn !=
MSA_OFF) {
04131
InflateRect((PRECT)lParam, 0, -
gcyMenuScrollArrow);
04132 }
04133
break;
04134
04135
case WM_ERASEBKGND:
04136
if (pmenu->
hbrBack !=
NULL) {
04137
MNEraseBackground ((HDC) wParam, pmenu,
04138 0, 0,
04139 pwnd->
rcClient.right - pwnd->
rcClient.left,
04140 pwnd->
rcClient.bottom - pwnd->
rcClient.top);
04141
return TRUE;
04142 }
else {
04143
goto CallDWP;
04144 }
04145
break;
04146
04147
case WM_PRINT:
04148
04149
04150
04151
04152
04153
04154
if ((lParam & PRF_NONCLIENT) && (pmenu->
dwArrowsOn !=
MSA_OFF)) {
04155
04156
MNDrawFullNC(pwnd, (HDC)wParam, ppopupmenu);
04157 GreGetWindowOrg((HDC)wParam, &ptOrg);
04158 GreSetWindowOrg((HDC)wParam,
04159 ptOrg.x -
MNXBORDER,
04160 ptOrg.y -
MNYBORDER -
gcyMenuScrollArrow,
04161
NULL);
04162
xxxDefWindowProc(pwnd, message, wParam, lParam & ~PRF_NONCLIENT);
04163 GreSetWindowOrg((HDC)wParam, ptOrg.x, ptOrg.y,
NULL);
04164
04165 }
else {
04166
goto CallDWP;
04167 }
04168
break;
04169
04170
case WM_WINDOWPOSCHANGING:
04171
if (!(((LPWINDOWPOS)lParam)->flags & SWP_SHOWWINDOW))
04172
goto CallDWP;
04173
04174
if (!
TestEffectUP(MENUANIMATION) || !(ppopupmenu->
iDropDir &
PAS_OUT)
04175 || (
GetAppCompatFlags2(
VER40) & GACF2_ANIMATIONOFF)) {
04176 NoAnimation:
04177 ppopupmenu->
iDropDir &= ~
PAS_OUT;
04178
goto CallDWP;
04179 }
04180
04181
04182
04183
04184 pMenuState->
cxAni = pwnd->
rcWindow.right - pwnd->
rcWindow.left;
04185 pMenuState->
cyAni = pwnd->
rcWindow.bottom - pwnd->
rcWindow.top;
04186
04187
if (
TestALPHA(MENUFADE)) {
04188
if ((hdcAni =
CreateFade(pwnd,
NULL,
CMS_MENUFADE,
04189
FADE_SHOW |
FADE_MENU)) ==
NULL) {
04190
goto NoAnimation;
04191 }
04192 }
else {
04193
04194
if (!
MNCreateAnimationBitmap(pMenuState, pMenuState->
cxAni,
04195 pMenuState->
cyAni)) {
04196
goto NoAnimation;
04197 }
04198
04199
04200
04201
04202 UserAssert(pMenuState->
hdcWndAni ==
NULL);
04203
04204
04205
04206
04207 UserAssert(pMenuState->
pGlobalPopupMenu->
spwndActivePopup == pwnd);
04208
04209
04210
04211
04212 pMenuState->
hdcWndAni =
_GetDCEx(pwnd,
HRGN_FULL, DCX_WINDOW | DCX_USESTYLE | DCX_INTERSECTRGN);
04213 pMenuState->
iAniDropDir = ppopupmenu->
iDropDir;
04214 pMenuState->
ixAni = (pMenuState->
iAniDropDir &
PAS_HORZ) ? 0 : pMenuState->
cxAni;
04215 pMenuState->
iyAni = (pMenuState->
iAniDropDir &
PAS_VERT) ? 0 : pMenuState->
cyAni;
04216 hdcAni = pMenuState->hdcAni;
04217 }
04218
04219
04220
04221
04222
04223
SetMF(pmenu,
MFWINDOWDC);
04224
04225
xxxSendMessage(pwnd, WM_PRINT, (WPARAM)hdcAni, PRF_CLIENT | PRF_NONCLIENT | PRF_ERASEBKGND);
04226
04227
ClearMF(pmenu,
MFWINDOWDC);
04228
04229
04230
04231
04232
04233
04234
04235
04236 UserAssert(GreValidateServerHandle(hdcAni, DC_TYPE));
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
if (
TestFadeFlags(
FADE_MENU)) {
04248
ShowFade();
04249 }
04250
goto CallDWP;
04251
04252
case WM_WINDOWPOSCHANGED:
04253
if (!(((LPWINDOWPOS)lParam)->flags & SWP_SHOWWINDOW))
04254
goto CallDWP;
04255
04256
04257
04258
04259
if (!(ppopupmenu->
iDropDir &
PAS_OUT))
04260
goto CallDWP;
04261
04262
04263
04264
04265
if (
TestFadeFlags(
FADE_MENU)) {
04266
StartFade();
04267 }
else {
04268 pMenuState->
dwAniStartTime =
NtGetTickCount();
04269
_SetTimer(pwnd,
IDSYS_MNANIMATE, 1,
NULL);
04270 }
04271 ppopupmenu->
iDropDir &= ~
PAS_OUT;
04272
goto CallDWP;
04273
04274
case WM_NCPAINT:
04275
04276
if (ppopupmenu->
iDropDir &
PAS_OUT) {
04277
04278
04279
04280
04281
04282
xxxValidateRect(pwnd,
NULL);
04283 }
else {
04284
04285
04286
04287
04288
if (pmenu->
dwArrowsOn !=
MSA_OFF) {
04289
04290 HDC hdc =
_GetDCEx(pwnd, (HRGN)wParam,
04291 DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN | DCX_NODELETERGN | DCX_LOCKWINDOWUPDATE);
04292
MNDrawFullNC(pwnd, hdc, ppopupmenu);
04293
_ReleaseDC(hdc);
04294 }
else {
04295
goto CallDWP;
04296 }
04297 }
04298
break;
04299
04300
case WM_PRINTCLIENT:
04301
ThreadLock(pmenu, &tlpmenu);
04302
xxxMenuDraw((HDC)wParam, pmenu);
04303
ThreadUnlock(&tlpmenu);
04304
break;
04305
04306
case WM_FINALDESTROY:
04307
04308
04309
04310 UserAssert((pMenuState ==
NULL) || (pMenuState->
hdcWndAni ==
NULL));
04311
04312
04313
04314
04315
if ((pMenuState !=
NULL) && pMenuState->
fDragAndDrop) {
04316
if (!SUCCEEDED(
xxxClientRevokeDragDrop(
HW(pwnd)))) {
04317 RIPMSG1(RIP_ERROR,
"xxxMenuWindowProc: xxxClientRevokeRegisterDragDrop failed:%#p", pwnd);
04318 }
04319 }
04320
04321
xxxMNDestroyHandler(ppopupmenu);
04322
return 0;
04323
04324
04325
case WM_PAINT:
04326
ThreadLock(pmenu, &tlpmenu);
04327
xxxBeginPaint(pwnd, &ps);
04328
xxxMenuDraw(ps.hdc, pmenu);
04329
xxxEndPaint(pwnd, &ps);
04330
ThreadUnlock(&tlpmenu);
04331
break;
04332
04333
case WM_CHAR:
04334
case WM_SYSCHAR:
04335
xxxMNChar(ppopupmenu, pMenuState, (
UINT)wParam);
04336
break;
04337
04338
case WM_KEYDOWN:
04339
case WM_SYSKEYDOWN:
04340
xxxMNKeyDown(ppopupmenu, pMenuState, (
UINT)wParam);
04341
break;
04342
04343
case WM_TIMER:
04344
switch (wParam) {
04345
case IDSYS_MNSHOW:
04346
04347
04348
04349
04350
04351
04352
04353 ppopupmenu->
fToggle =
FALSE;
04354
xxxMNOpenHierarchy(ppopupmenu, pMenuState);
04355
break;
04356
04357
case IDSYS_MNHIDE:
04358 ppopupmenu->
fToggle =
FALSE;
04359
xxxMNCloseHierarchy(ppopupmenu,pMenuState);
04360
break;
04361
04362
case IDSYS_MNUP:
04363
case IDSYS_MNDOWN:
04364
if (pMenuState->
fButtonDown) {
04365
xxxMNDoScroll(ppopupmenu, (
UINT)wParam,
FALSE);
04366 }
else {
04367
_KillTimer(pwnd, (
UINT)wParam);
04368 }
04369
break;
04370
04371
case IDSYS_MNANIMATE:
04372
if (pMenuState->
hdcWndAni !=
NULL) {
04373
MNAnimate(pMenuState,
TRUE);
04374 }
else {
04375
04376
04377
04378 UserAssert(pMenuState->
hdcWndAni !=
NULL);
04379 }
04380
break;
04381
04382
case IDSYS_MNAUTODISMISS:
04383
04384
04385
04386
04387
_KillTimer(pwnd,
IDSYS_MNAUTODISMISS);
04388
if (pMenuState->
fAboutToAutoDismiss) {
04389
goto EndMenu;
04390 }
04391 }
04392
break;
04393
04394
04395
04396
04397
case MN_SETHMENU:
04398
04399
04400
04401
04402
04403
04404
if (wParam != 0) {
04405
if ((wParam = (WPARAM)
ValidateHmenu((HMENU)wParam)) == 0) {
04406
break;
04407 }
04408
LockPopupMenu(ppopupmenu, &(ppopupmenu->
spmenu), (
PMENU)wParam);
04409 }
else {
04410 RIPMSG1(RIP_ERROR,
"xxxMenuWindowProc: MN_SETHMENU ignoring NULL wParam. pwnd:%p", pwnd);
04411 }
04412
break;
04413
04414
case MN_GETHMENU:
04415
04416
04417
04418
04419
return (LRESULT)
PtoH(pmenu);
04420
04421
case MN_SIZEWINDOW:
04422 {
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
int cx,
cy;
04435
PMONITOR pMonitor;
04436
04437
04438
04439
04440
04441
if (pmenu ==
NULL)
04442
break;
04443
04444
ThreadLockAlways(pmenu, &tlpmenu);
04445
ThreadLock(ppopupmenu->
spwndNotify, &tlpwndNotify);
04446 UserAssert(pmenu->
spwndNotify == ppopupmenu->
spwndNotify);
04447
xxxMNCompute(pmenu, ppopupmenu->
spwndNotify, 0, 0, 0, 0);
04448
ThreadUnlock(&tlpwndNotify);
04449
ThreadUnlock(&tlpmenu);
04450
04451 pMonitor =
_MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY);
04452 cx = pmenu->
cxMenu;
04453
cy =
MNCheckScroll(pmenu, pMonitor);
04454
04455
04456
04457
04458
if (wParam != 0) {
04459 LONG lPos;
04460
int x, y;
04461
DWORD dwFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER;
04462
04463
04464
04465
04466
if (wParam &
MNSW_DRAWFRAME) {
04467
dwFlags |= SWP_DRAWFRAME;
04468 }
04469
04470
04471
04472
04473
04474
04475
if (
TestWF(pwnd,
WFVISIBLE)) {
04476 lPos =
FindBestPos(
04477 pwnd->
rcWindow.left,
04478 pwnd->
rcWindow.top,
04479 cx,
04480
cy,
04481
NULL,
04482 0,
04483 ppopupmenu,
04484 pMonitor);
04485
04486 x =
GET_X_LPARAM(lPos);
04487 y =
GET_Y_LPARAM(lPos);
04488 }
else {
04489
dwFlags |= SWP_NOMOVE;
04490 }
04491
04492
xxxSetWindowPos(
04493 pwnd,
04494
PWND_TOP,
04495 x,
04496 y,
04497 cx + 2*
SYSMET(CXFIXEDFRAME),
04498
cy + 2*
SYSMET(CYFIXEDFRAME),
04499
dwFlags);
04500
04501 }
04502
04503
return MAKELONG(cx,
cy);
04504 }
04505
04506
case MN_OPENHIERARCHY:
04507 {
04508
PWND pwndT;
04509
04510
04511
04512
04513 pwndT =
xxxMNOpenHierarchy(ppopupmenu, pMenuState);
04514
return (LRESULT)
HW(pwndT);
04515 }
04516
04517
case MN_CLOSEHIERARCHY:
04518
xxxMNCloseHierarchy(ppopupmenu, pMenuState);
04519
break;
04520
04521
case MN_SELECTITEM:
04522
04523
04524
04525
04526
if ((wParam >= pmenu->
cItems) && (wParam <
MFMWFP_MINVALID)) {
04527 UserAssertMsg1(
FALSE,
"Bad wParam %x for MN_SELECTITEM", wParam);
04528
break;
04529 }
04530
04531 pItem =
xxxMNSelectItem(ppopupmenu, pMenuState, (
UINT)wParam);
04532
if (pItem !=
NULL) {
04533
return((LONG)(
DWORD)(WORD)(pItem->
fState |
04534 ((pItem->
spSubMenu !=
NULL) ? MF_POPUP : 0)));
04535 }
04536
04537
break;
04538
04539
case MN_SELECTFIRSTVALIDITEM: {
04540
UINT item;
04541
04542 item =
MNFindNextValidItem(pmenu, -1, 1,
TRUE);
04543
xxxSendMessage(pwnd, MN_SELECTITEM, item, 0
L);
04544
return (LONG)item;
04545 }
04546
04547
case MN_CANCELMENUS:
04548
04549
04550
04551
04552
04553
04554
xxxMNCancel(pMenuState, (
UINT)wParam, (
BOOL)LOWORD(lParam), 0);
04555
break;
04556
04557
case MN_FINDMENUWINDOWFROMPOINT:
04558
04559
04560
04561
04562 lRet =
xxxMNFindWindowFromPoint(ppopupmenu, (
PUINT)wParam, MAKEPOINTS(lParam));
04563
04564
04565
04566
04567
if (
IsMFMWFPWindow(lRet)) {
04568
return (LRESULT)
HW((
PWND)lRet);
04569 }
else {
04570
return lRet;
04571 }
04572
04573
04574
case MN_SHOWPOPUPWINDOW:
04575
04576
04577
04578
PlayEventSound(
USER_SOUND_MENUPOPUP);
04579
xxxShowWindow(pwnd, (pMenuState->
fModelessMenu ? SW_SHOW : SW_SHOWNOACTIVATE));
04580
break;
04581
04582
case MN_ACTIVATEPOPUP:
04583
04584
04585
04586
04587 UserAssert(pMenuState->
fModelessMenu);
04588
xxxActivateThisWindow(pwnd, 0, 0);
04589
break;
04590
04591
case MN_ENDMENU:
04592
04593
04594
04595
04596
04597 EndMenu:
04598
xxxEndMenuLoop(pMenuState, pMenuState->
pGlobalPopupMenu);
04599
if (pMenuState->
fModelessMenu) {
04600 UserAssert(!pMenuState->
fInCallHandleMenuMessages);
04601
xxxMNEndMenuState(
TRUE);
04602 }
04603
return 0;
04604
04605
case MN_DODRAGDROP:
04606
04607
04608
04609
if (pMenuState->
fDragging
04610 && (ppopupmenu->
spwndNotify !=
NULL)
04611 &&
IsMFMWFPWindow(pMenuState->
uButtonDownHitArea)) {
04612
04613
04614
04615 pmenu = (((
PMENUWND)pMenuState->
uButtonDownHitArea)->ppopupmenu)->spmenu;
04616
04617
04618
04619
04620
if (!pMenuState->
fModelessMenu) {
04621 UserAssert(
PtiCurrent()->pq->QF_flags &
QF_CAPTURELOCKED);
04622
PtiCurrent()->pq->QF_flags &= ~
QF_CAPTURELOCKED;
04623 }
04624
04625
LockMenuState(pMenuState);
04626
ThreadLockAlways(ppopupmenu->
spwndNotify, &tlpwndNotify);
04627
04628
04629
04630
04631 pMenuState->
fInDoDragDrop =
TRUE;
04632 lRet =
xxxSendMessage(ppopupmenu->
spwndNotify, WM_MENUDRAG,
04633 pMenuState->
uButtonDownIndex, (LPARAM)
PtoH(pmenu));
04634 pMenuState->
fInDoDragDrop =
FALSE;
04635
04636
if (lRet == MND_ENDMENU) {
04637
04638
04639
04640
ThreadUnlock(&tlpwndNotify);
04641
if (!
xxxUnlockMenuState(pMenuState)) {
04642
goto EndMenu;
04643 }
else {
04644
return 0;
04645 }
04646
break;
04647 }
else {
04648
04649
04650
04651
04652 pMenuState->
fIgnoreButtonUp =
TRUE;
04653 }
04654
04655
04656
04657
04658
04659
MNCheckButtonDownState(pMenuState);
04660
04661
04662
04663
04664
if (!pMenuState->
fModelessMenu) {
04665
xxxMNSetCapture(ppopupmenu);
04666 }
04667
04668
ThreadUnlock(&tlpwndNotify);
04669
xxxUnlockMenuState(pMenuState);
04670 }
04671
return 0;
04672
04673
case MN_BUTTONDOWN:
04674
04675
04676
04677
04678
04679
if ((wParam >= pmenu->
cItems) && (wParam <
MFMWFP_MINVALID)) {
04680 UserAssertMsg1(
FALSE,
"Bad wParam %x for MN_BUTTONDOWN", wParam);
04681
break;
04682 }
04683
xxxMNButtonDown(ppopupmenu, pMenuState, (
UINT)wParam,
TRUE);
04684
break;
04685
04686
case MN_MOUSEMOVE:
04687
04688
04689
04690
04691
xxxMNMouseMove(ppopupmenu, pMenuState, MAKEPOINTS(lParam));
04692
break;
04693
04694
case MN_BUTTONUP:
04695
04696
04697
04698
04699
if ((wParam >= pmenu->
cItems) && (wParam <
MFMWFP_MINVALID)) {
04700 UserAssertMsg1(
FALSE,
"Bad wParam %x for MN_BUTTONUP", wParam);
04701
break;
04702 }
04703
xxxMNButtonUp(ppopupmenu, pMenuState, (
UINT)wParam, lParam);
04704
break;
04705
04706
case MN_SETTIMERTOOPENHIERARCHY:
04707
04708
04709
04710
04711
04712
return (LONG)(WORD)
MNSetTimerToOpenHierarchy(ppopupmenu);
04713
04714
case MN_DBLCLK:
04715
04716
04717
04718
xxxMNDoubleClick(pMenuState, ppopupmenu, (
int)wParam);
04719
break;
04720
04721
case WM_MOUSELEAVE:
04722 UserAssert(pMenuState->
fModelessMenu);
04723
04724
04725
04726
04727 pMenuState->
fMouseOffMenu = !pMenuState->
fInDoDragDrop;
04728 ppopupmenu->
fTrackMouseEvent =
FALSE;
04729
04730
04731
04732
MNSetTimerToAutoDismiss(pMenuState, pwnd);
04733
04734
04735
04736
if (ppopupmenu->
spwndPopupMenu == pMenuState->
pGlobalPopupMenu->
spwndActivePopup) {
04737
xxxMNSelectItem(ppopupmenu, pMenuState,
MFMWFP_NOITEM);
04738 }
04739
break;
04740
04741
case WM_ACTIVATEAPP:
04742
if (pMenuState->
fModelessMenu
04743 && (pwnd == pMenuState->
pGlobalPopupMenu->
spwndActivePopup)) {
04744
04745
04746
04747
04748
if (wParam) {
04749
_PostMessage(pwnd, MN_ACTIVATEPOPUP, 0, 0);
04750
04751
04752
04753
04754
04755
04756
04757 pMenuState->
fActiveNoForeground = (
gpqForeground !=
PtiCurrent()->pq);
04758 }
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
if (ppopupmenu->
spwndNotify !=
NULL) {
04769
ThreadLockAlways(ppopupmenu->
spwndNotify, &tlpwndNotify);
04770
xxxDWP_DoNCActivate(ppopupmenu->
spwndNotify,
04771 ((wParam && !pMenuState->
fActiveNoForeground) ?
NCA_ACTIVE :
NCA_FORCEFRAMEOFF),
04772
HRGN_FULL);
04773
ThreadUnlock(&tlpwndNotify);
04774 }
04775 }
04776
break;
04777
04778
case WM_ACTIVATE:
04779
if (pMenuState->
fModelessMenu) {
04780
04781
04782
04783
04784
if ((LOWORD(wParam) == WA_INACTIVE)
04785 && !pMenuState->
fInCallHandleMenuMessages
04786 && !pMenuState->
pGlobalPopupMenu->
fInCancel) {
04787
04788 lParam = (LPARAM)
RevalidateHwnd((HWND)lParam);
04789
if ((lParam != 0)
04790 && ((
GETFNID((
PWND)lParam) !=
FNID_MENU)
04791 ||
IsRecursedMenuState(pMenuState, ((
PMENUWND)lParam)->ppopupmenu))) {
04792
04793
04794
04795
04796
if (pMenuState->
fActiveNoForeground
04797 && (
gpqForeground ==
PtiCurrent()->pq)) {
04798
04799 pMenuState->
fActiveNoForeground =
FALSE;
04800
_PostMessage(pwnd, MN_ACTIVATEPOPUP, 0, 0);
04801 }
else {
04802
04803
04804
04805
04806
04807
04808
_PostMessage(pwnd, MN_ENDMENU, 0, 0);
04809
break;
04810 }
04811 }
04812 }
04813
goto CallDWP;
04814 }
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
if (LOWORD(wParam)) {
04830
TL tlpwnd;
04831
04832
04833
04834
if (
Is500Compat(
PtiCurrent()->dwExpWinVer)) {
04835 RIPMSG1(RIP_ERROR,
"xxxMenuWindowProc: Menu window activated:%#p", pwnd);
04836
_PostMessage(pwnd, MN_ENDMENU, 0, 0);
04837
break;
04838 }
04839
04840
#if 0
04841
04842
04843
04844
xxxActivateWindow(pwnd,
AW_SKIP2);
04845
#else
04846
04847
04848
04849
if ((
gpqForegroundPrev !=
NULL) &&
04850 !
FBadWindow(
gpqForegroundPrev->
spwndActivePrev) &&
04851 !
ISAMENU(
gpqForegroundPrev->
spwndActivePrev)) {
04852 pwnd =
gpqForegroundPrev->
spwndActivePrev;
04853 }
else {
04854
04855
04856
04857
04858
04859
04860
04861
04862
PWND pwndMenu = pwnd;
04863
UINT uCounter = 0;
04864
do {
04865 pwnd =
NextTopWindow(
PtiCurrent(), pwnd,
NULL, 0);
04866
if (pwnd && !
FBadWindow(pwnd->
spwndLastActive) &&
04867 !
ISAMENU(pwnd->
spwndLastActive)) {
04868 pwnd = pwnd->
spwndLastActive;
04869 uCounter = 0;
04870
break;
04871 }
04872 }
while ((pwnd !=
NULL) && (uCounter++ < 255));
04873
04874
04875
04876
if (uCounter != 0) {
04877 RIPMSG0(RIP_ERROR,
"xxxMenuWindowProc: couldn't fix active window");
04878
_PostMessage(pwndMenu, MN_ENDMENU, 0, 0);
04879
break;
04880 }
04881 }
04882
04883
if (pwnd !=
NULL) {
04884
PTHREADINFO pti =
PtiCurrent();
04885
ThreadLockAlwaysWithPti(pti, pwnd, &tlpwnd);
04886
04887
04888
04889
04890
04891
if (
GETPTI(pwnd)->pq != pti->
pq) {
04892
04893
04894
04895
04896
if (
gpqForeground == pti->
pq) {
04897
xxxSetForegroundWindow(pwnd,
FALSE);
04898 }
04899 }
else {
04900
xxxActivateThisWindow(pwnd, 0,
ATW_SETFOCUS);
04901 }
04902
04903
ThreadUnlock(&tlpwnd);
04904 }
04905
#endif
04906
}
04907
break;
04908
04909
case WM_SIZE:
04910
case WM_MOVE:
04911
04912
04913
04914
04915
if (ppopupmenu->
spwndNextPopup !=
NULL) {
04916 pItem =
MNGetpItem(ppopupmenu, ppopupmenu->
posDropped);
04917
if (pItem !=
NULL) {
04918
int x, y;
04919
PMONITOR pMonitorDummy;
04920
04921
04922
04923
04924
#define pmenuNext (((PMENUWND)ppopupmenu->spwndNextPopup)->ppopupmenu->spmenu)
04925
if (
pmenuNext->cxMenu == 0) {
04926
xxxSendMessage(ppopupmenu->
spwndNextPopup, MN_SIZEWINDOW,
MNSW_RETURNSIZE, 0
L);
04927 }
04928
04929
04930
04931
04932
xxxMNPositionHierarchy(ppopupmenu, pItem,
04933
pmenuNext->cxMenu + (2 *
SYSMET(CXFIXEDFRAME)),
04934
pmenuNext->cyMenu + (2 *
SYSMET(CXFIXEDFRAME)),
04935 &x, &y, &pMonitorDummy);
04936
04937
04938
04939
04940
ThreadLockAlways(ppopupmenu->
spwndNextPopup, &tlpwndNotify);
04941
xxxSetWindowPos(ppopupmenu->
spwndNextPopup,
NULL,
04942 x, y, 0, 0,
04943 SWP_NOSIZE | SWP_NOZORDER | SWP_NOSENDCHANGING);
04944
ThreadUnlock(&tlpwndNotify);
04945
#undef pmenuNext
04946
}
04947 }
04948
break;
04949
04950
case WM_NCHITTEST:
04951
04952
04953
04954
04955
04956
04957
04958
if (pMenuState->
fModelessMenu) {
04959 ptOrg.x =
GET_X_LPARAM(lParam);
04960 ptOrg.y =
GET_Y_LPARAM(lParam);
04961
if (
PtInRect(&pwnd->
rcWindow, ptOrg)) {
04962
return HTCLIENT;
04963 }
else {
04964
return HTNOWHERE;
04965 }
04966 }
else {
04967
goto CallDWP;
04968 }
04969
04970
04971
default:
04972 CallDWP:
04973
return xxxDefWindowProc(pwnd, message, wParam, lParam);
04974 }
04975
04976
return 0;
04977 }