Skip to content

Commit d52cac4

Browse files
committed
[0.4.12][WIN32SS] MENU_ShowPopup() We chicken out for this rls still
as the release data is close and we have to manage the risk. This reverts last commit and all menu related code back to the state of 0.4.12-dev-369-g 007ec03 Although Mark Jansen seems to be on a very promising path in master, we still revert one last time for this release to the more well known state we had during 0.4.12dev'ing. This will fix regressions CORE-16298, CORE-16297 and will keep CORE-15863 in fixed state. Systray and nested desktop popups do work very well like this. We therefore intentionally and willingly have to accept the broken partial-offscreen-menus of CORE-15733. Those are not as important as the other tickets. Meanwhile we keep on improving master based on the more recent states.
1 parent 3113d13 commit d52cac4

File tree

1 file changed

+57
-190
lines changed

1 file changed

+57
-190
lines changed

win32ss/user/ntuser/menu.c

Lines changed: 57 additions & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -2860,122 +2860,29 @@ static BOOL MENU_InitPopup( PWND pWndOwner, PMENU menu, UINT flags )
28602860
return TRUE;
28612861
}
28622862

2863-
2864-
#define SHOW_DEBUGRECT 0
2865-
2866-
#if SHOW_DEBUGRECT
2867-
static void DebugRect(const RECT* rectl, COLORREF color)
2868-
{
2869-
HBRUSH brush;
2870-
RECT rr;
2871-
HDC hdc;
2872-
2873-
if (!rectl)
2874-
return;
2875-
2876-
hdc = UserGetDCEx(NULL, 0, DCX_USESTYLE);
2877-
2878-
brush = IntGdiCreateSolidBrush(color);
2879-
2880-
rr = *rectl;
2881-
RECTL_vInflateRect(&rr, 1, 1);
2882-
FrameRect(hdc, rectl, brush);
2883-
FrameRect(hdc, &rr, brush);
2884-
2885-
NtGdiDeleteObjectApp(brush);
2886-
UserReleaseDC(NULL, hdc, TRUE);
2887-
}
2888-
2889-
static void DebugPoint(INT x, INT y, COLORREF color)
2890-
{
2891-
RECT rr = {x, y, x, y};
2892-
DebugRect(&rr, color);
2893-
}
2894-
#endif
2895-
2896-
static BOOL RECTL_Intersect(const RECT* pRect, INT x, INT y, UINT width, UINT height)
2897-
{
2898-
RECT other = {x, y, x + width, y + height};
2899-
RECT dum;
2900-
2901-
return RECTL_bIntersectRect(&dum, pRect, &other);
2902-
}
2903-
2904-
static BOOL MENU_MoveRect(UINT flags, INT* x, INT* y, INT width, INT height, const RECT* pExclude, PMONITOR monitor)
2905-
{
2906-
/* Figure out if we should move vertical or horizontal */
2907-
if (flags & TPM_VERTICAL)
2908-
{
2909-
/* Move in the vertical direction: TPM_BOTTOMALIGN means drop it above, otherways drop it below */
2910-
if (flags & TPM_BOTTOMALIGN)
2911-
{
2912-
if (pExclude->top - height >= monitor->rcMonitor.top)
2913-
{
2914-
*y = pExclude->top - height;
2915-
return TRUE;
2916-
}
2917-
}
2918-
else
2919-
{
2920-
if (pExclude->bottom + height < monitor->rcMonitor.bottom)
2921-
{
2922-
*y = pExclude->bottom;
2923-
return TRUE;
2924-
}
2925-
}
2926-
}
2927-
else
2928-
{
2929-
/* Move in the horizontal direction: TPM_RIGHTALIGN means drop it to the left, otherways go right */
2930-
if (flags & TPM_RIGHTALIGN)
2931-
{
2932-
if (pExclude->left - width >= monitor->rcMonitor.left)
2933-
{
2934-
*x = pExclude->left - width;
2935-
return TRUE;
2936-
}
2937-
}
2938-
else
2939-
{
2940-
if (pExclude->right + width < monitor->rcMonitor.right)
2941-
{
2942-
*x = pExclude->right;
2943-
return TRUE;
2944-
}
2945-
}
2946-
}
2947-
return FALSE;
2948-
}
2949-
29502863
/***********************************************************************
29512864
* MenuShowPopup
29522865
*
29532866
* Display a popup menu.
29542867
*/
29552868
static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT flags,
2956-
INT x, INT y, const RECT* pExclude)
2869+
INT x, INT y, INT xanchor, INT yanchor )
29572870
{
29582871
UINT width, height;
2959-
POINT ptx;
2872+
POINT pt;
29602873
PMONITOR monitor;
29612874
PWND pWnd;
29622875
USER_REFERENCE_ENTRY Ref;
2963-
BOOL bIsPopup = (flags & TPM_POPUPMENU) != 0;
29642876

2965-
TRACE("owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x\n",
2966-
pwndOwner, menu, id, x, y);
2877+
TRACE("owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
2878+
pwndOwner, menu, id, x, y, xanchor, yanchor);
29672879

29682880
if (menu->iItem != NO_SELECTED_ITEM)
29692881
{
29702882
menu->rgItems[menu->iItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
29712883
menu->iItem = NO_SELECTED_ITEM;
29722884
}
29732885

2974-
#if SHOW_DEBUGRECT
2975-
if (pExclude)
2976-
DebugRect(pExclude, RGB(255, 0, 0));
2977-
#endif
2978-
29792886
menu->dwArrowsOn = 0;
29802887
MENU_PopupMenuCalcSize(menu, pwndOwner);
29812888

@@ -2984,102 +2891,67 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl
29842891
width = menu->cxMenu + UserGetSystemMetrics(SM_CXBORDER);
29852892
height = menu->cyMenu + UserGetSystemMetrics(SM_CYBORDER);
29862893

2987-
if (flags & TPM_LAYOUTRTL)
2988-
flags ^= TPM_RIGHTALIGN;
2989-
2990-
if (flags & TPM_RIGHTALIGN)
2991-
x -= width;
2992-
if (flags & TPM_CENTERALIGN)
2993-
x -= width / 2;
2994-
2995-
if (flags & TPM_BOTTOMALIGN)
2996-
y -= height;
2997-
if (flags & TPM_VCENTERALIGN)
2998-
y -= height / 2;
2999-
30002894
/* FIXME: should use item rect */
3001-
ptx.x = x;
3002-
ptx.y = y;
3003-
#if SHOW_DEBUGRECT
3004-
DebugPoint(x, y, RGB(0, 0, 255));
3005-
#endif
3006-
monitor = UserMonitorFromPoint( ptx, MONITOR_DEFAULTTONEAREST );
2895+
pt.x = x;
2896+
pt.y = y;
2897+
monitor = UserMonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
30072898

3008-
/* We are off the right side of the screen */
3009-
if (x + width > monitor->rcMonitor.right)
3010-
{
3011-
if ((x - width) < monitor->rcMonitor.left || x >= monitor->rcMonitor.right)
3012-
x = monitor->rcMonitor.right - width;
3013-
else
3014-
x -= width;
3015-
}
2899+
if (flags & TPM_LAYOUTRTL)
2900+
flags ^= TPM_RIGHTALIGN;
30162901

3017-
/* We are off the left side of the screen */
3018-
if (x < monitor->rcMonitor.left)
3019-
{
3020-
/* Re-orient the menu around the x-axis */
3021-
x += width;
2902+
if( flags & TPM_RIGHTALIGN ) x -= width;
2903+
if( flags & TPM_CENTERALIGN ) x -= width / 2;
30222904

3023-
if (x < monitor->rcMonitor.left || x >= monitor->rcMonitor.right || bIsPopup)
3024-
x = monitor->rcMonitor.left;
3025-
}
2905+
if( flags & TPM_BOTTOMALIGN ) y -= height;
2906+
if( flags & TPM_VCENTERALIGN ) y -= height / 2;
30262907

3027-
/* Same here, but then the top */
3028-
if (y < monitor->rcMonitor.top)
2908+
if( x + width > monitor->rcMonitor.right)
30292909
{
3030-
y += height;
2910+
if( xanchor && x >= width - xanchor )
2911+
x -= width - xanchor;
30312912

3032-
if (y < monitor->rcMonitor.top || y >= monitor->rcMonitor.bottom || bIsPopup)
3033-
y = monitor->rcMonitor.top;
2913+
if( x + width > monitor->rcMonitor.right)
2914+
{
2915+
/* If we would flip around our origin, would we go off screen on the other side?
2916+
Or is our origin itself too far to the right already? */
2917+
if (x - width < monitor->rcMonitor.left || x > monitor->rcMonitor.right)
2918+
x = monitor->rcMonitor.right - width;
2919+
else
2920+
x -= width;
2921+
}
30342922
}
3035-
3036-
/* And the bottom */
3037-
if (y + height > monitor->rcMonitor.bottom)
2923+
if( x < monitor->rcMonitor.left )
30382924
{
3039-
if ((y - height) < monitor->rcMonitor.top || y >= monitor->rcMonitor.bottom || bIsPopup)
3040-
y = monitor->rcMonitor.bottom - height;
2925+
/* If we would flip around our origin, would we go off screen on the other side? */
2926+
if (x + width > monitor->rcMonitor.right)
2927+
x = monitor->rcMonitor.left;
30412928
else
3042-
y -= height;
2929+
x += width;
30432930
}
30442931

3045-
if (pExclude)
2932+
if( y + height > monitor->rcMonitor.bottom)
30462933
{
3047-
RECT Cleaned;
2934+
if( yanchor && y >= height + yanchor )
2935+
y -= height + yanchor;
30482936

3049-
if (RECTL_bIntersectRect(&Cleaned, pExclude, &monitor->rcMonitor) &&
3050-
RECTL_Intersect(&Cleaned, x, y, width, height))
2937+
if( y + height > monitor->rcMonitor.bottom)
30512938
{
3052-
UINT flag_mods[] = {
3053-
0, /* First try the 'normal' way */
3054-
TPM_BOTTOMALIGN | TPM_RIGHTALIGN, /* Then try the opposite side */
3055-
TPM_VERTICAL, /* Then swap horizontal / vertical */
3056-
TPM_BOTTOMALIGN | TPM_RIGHTALIGN | TPM_VERTICAL, /* Then the other side again (still swapped hor/ver) */
3057-
};
3058-
UINT n;
3059-
for (n = 0; n < RTL_NUMBER_OF(flag_mods); ++n)
3060-
{
3061-
INT tx = x;
3062-
INT ty = y;
3063-
3064-
/* Try to move a bit around */
3065-
if (MENU_MoveRect(flags ^ flag_mods[n], &tx, &ty, width, height, &Cleaned, monitor) &&
3066-
!RECTL_Intersect(&Cleaned, tx, ty, width, height))
3067-
{
3068-
x = tx;
3069-
y = ty;
3070-
break;
3071-
}
3072-
}
3073-
/* If none worked, we go with the original x/y */
2939+
/* If we would flip around our origin, would we go off screen on the other side?
2940+
Or is our origin itself too far to the bottom already? */
2941+
if (y - height < monitor->rcMonitor.top || y > monitor->rcMonitor.bottom)
2942+
y = monitor->rcMonitor.bottom - height;
2943+
else
2944+
y -= height;
30742945
}
30752946
}
3076-
3077-
#if SHOW_DEBUGRECT
2947+
if( y < monitor->rcMonitor.top )
30782948
{
3079-
RECT rr = {x, y, x + width, y + height};
3080-
DebugRect(&rr, RGB(0, 255, 0));
2949+
/* If we would flip around our origin, would we go off screen on the other side? */
2950+
if (y + height > monitor->rcMonitor.bottom)
2951+
y = monitor->rcMonitor.top;
2952+
else
2953+
y += height;
30812954
}
3082-
#endif
30832955

30842956
pWnd = ValidateHwndNoErr( menu->hWnd );
30852957

@@ -3327,7 +3199,7 @@ static void FASTCALL MENU_HideSubPopups(PWND pWndOwner, PMENU Menu,
33273199
*/
33283200
static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFirst, UINT Flags)
33293201
{
3330-
RECT Rect, ParentRect;
3202+
RECT Rect;
33313203
ITEM *Item;
33323204
HDC Dc;
33333205
PWND pWnd;
@@ -3362,13 +3234,6 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
33623234

33633235
pWnd = ValidateHwndNoErr(Menu->hWnd);
33643236

3365-
/* Grab the rect of our (entire) parent menu, so we can try to not overlap it */
3366-
if (!IntGetWindowRect(pWnd, &ParentRect))
3367-
{
3368-
ERR("No pWnd\n");
3369-
ParentRect = Rect;
3370-
}
3371-
33723237
/* correct item if modified as a reaction to WM_INITMENUPOPUP message */
33733238
if (!(Item->fState & MF_HILITE))
33743239
{
@@ -3445,7 +3310,7 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
34453310
MENU_InitPopup( WndOwner, Item->spSubMenu, Flags );
34463311

34473312
MENU_ShowPopup( WndOwner, Item->spSubMenu, Menu->iItem, Flags,
3448-
Rect.left, Rect.top, &ParentRect);
3313+
Rect.left, Rect.top, Rect.right, Rect.bottom );
34493314
if (SelectFirst)
34503315
{
34513316
MENU_MoveSelection(WndOwner, Item->spSubMenu, ITEM_NEXT);
@@ -4045,7 +3910,7 @@ static void FASTCALL MENU_KeyRight(MTRACKER *pmt, UINT Flags, UINT msg)
40453910
* Menu tracking code.
40463911
*/
40473912
static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
4048-
PWND pwnd)
3913+
PWND pwnd, const RECT *lprect )
40493914
{
40503915
MSG msg;
40513916
BOOL fRemove;
@@ -4068,8 +3933,9 @@ static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
40683933
mt.Pt.x = x;
40693934
mt.Pt.y = y;
40703935

4071-
TRACE("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x\n",
4072-
UserHMGetHandle(pmenu), wFlags, x, y, UserHMGetHandle(pwnd));
3936+
TRACE("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n",
3937+
UserHMGetHandle(pmenu), wFlags, x, y, UserHMGetHandle(pwnd), lprect ? lprect->left : 0, lprect ? lprect->top : 0,
3938+
lprect ? lprect->right : 0, lprect ? lprect->bottom : 0);
40733939

40743940
pti->MessageQueue->QF_flags &= ~QF_ACTIVATIONCHANGE;
40753941

@@ -4480,7 +4346,7 @@ VOID MENU_TrackMouseMenuBar( PWND pWnd, ULONG ht, POINT pt)
44804346
MENU_InitTracking(pWnd, pMenu, FALSE, wFlags);
44814347
/* fetch the window menu again, it may have changed */
44824348
pMenu = (ht == HTSYSMENU) ? get_win_sys_menu( UserHMGetHandle(pWnd) ) : IntGetMenu( UserHMGetHandle(pWnd) );
4483-
MENU_TrackMenu(pMenu, wFlags, pt.x, pt.y, pWnd);
4349+
MENU_TrackMenu(pMenu, wFlags, pt.x, pt.y, pWnd, NULL);
44844350
MENU_ExitTracking(pWnd, FALSE, wFlags);
44854351
}
44864352
}
@@ -4544,7 +4410,7 @@ VOID MENU_TrackKbdMenuBar(PWND pwnd, UINT wParam, WCHAR wChar)
45444410
}
45454411

45464412
track_menu:
4547-
MENU_TrackMenu( TrackMenu, wFlags, 0, 0, pwnd );
4413+
MENU_TrackMenu( TrackMenu, wFlags, 0, 0, pwnd, NULL );
45484414
MENU_ExitTracking( pwnd, FALSE, wFlags);
45494415
}
45504416

@@ -4586,8 +4452,9 @@ BOOL WINAPI IntTrackPopupMenuEx( PMENU menu, UINT wFlags, int x, int y,
45864452
if (menu->fFlags & MNF_SYSMENU)
45874453
MENU_InitSysMenuPopup( menu, pWnd->style, pWnd->pcls->style, HTSYSMENU);
45884454

4589-
if (MENU_ShowPopup(pWnd, menu, 0, wFlags | TPM_POPUPMENU, x, y, lpTpm ? &lpTpm->rcExclude : NULL))
4590-
ret = MENU_TrackMenu( menu, wFlags | TPM_POPUPMENU, 0, 0, pWnd);
4455+
if (MENU_ShowPopup(pWnd, menu, 0, wFlags, x, y, 0, 0 ))
4456+
ret = MENU_TrackMenu( menu, wFlags | TPM_POPUPMENU, 0, 0, pWnd,
4457+
lpTpm ? &lpTpm->rcExclude : NULL);
45914458
else
45924459
{
45934460
MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);

0 commit comments

Comments
 (0)