[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
007ec0310c

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.
This commit is contained in:
Joachim Henze 2019-08-07 23:07:33 +02:00
parent 3113d13793
commit d52cac4ca1

View file

@ -2860,110 +2860,22 @@ static BOOL MENU_InitPopup( PWND pWndOwner, PMENU menu, UINT flags )
return TRUE;
}
#define SHOW_DEBUGRECT 0
#if SHOW_DEBUGRECT
static void DebugRect(const RECT* rectl, COLORREF color)
{
HBRUSH brush;
RECT rr;
HDC hdc;
if (!rectl)
return;
hdc = UserGetDCEx(NULL, 0, DCX_USESTYLE);
brush = IntGdiCreateSolidBrush(color);
rr = *rectl;
RECTL_vInflateRect(&rr, 1, 1);
FrameRect(hdc, rectl, brush);
FrameRect(hdc, &rr, brush);
NtGdiDeleteObjectApp(brush);
UserReleaseDC(NULL, hdc, TRUE);
}
static void DebugPoint(INT x, INT y, COLORREF color)
{
RECT rr = {x, y, x, y};
DebugRect(&rr, color);
}
#endif
static BOOL RECTL_Intersect(const RECT* pRect, INT x, INT y, UINT width, UINT height)
{
RECT other = {x, y, x + width, y + height};
RECT dum;
return RECTL_bIntersectRect(&dum, pRect, &other);
}
static BOOL MENU_MoveRect(UINT flags, INT* x, INT* y, INT width, INT height, const RECT* pExclude, PMONITOR monitor)
{
/* Figure out if we should move vertical or horizontal */
if (flags & TPM_VERTICAL)
{
/* Move in the vertical direction: TPM_BOTTOMALIGN means drop it above, otherways drop it below */
if (flags & TPM_BOTTOMALIGN)
{
if (pExclude->top - height >= monitor->rcMonitor.top)
{
*y = pExclude->top - height;
return TRUE;
}
}
else
{
if (pExclude->bottom + height < monitor->rcMonitor.bottom)
{
*y = pExclude->bottom;
return TRUE;
}
}
}
else
{
/* Move in the horizontal direction: TPM_RIGHTALIGN means drop it to the left, otherways go right */
if (flags & TPM_RIGHTALIGN)
{
if (pExclude->left - width >= monitor->rcMonitor.left)
{
*x = pExclude->left - width;
return TRUE;
}
}
else
{
if (pExclude->right + width < monitor->rcMonitor.right)
{
*x = pExclude->right;
return TRUE;
}
}
}
return FALSE;
}
/***********************************************************************
* MenuShowPopup
*
* Display a popup menu.
*/
static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT flags,
INT x, INT y, const RECT* pExclude)
INT x, INT y, INT xanchor, INT yanchor )
{
UINT width, height;
POINT ptx;
POINT pt;
PMONITOR monitor;
PWND pWnd;
USER_REFERENCE_ENTRY Ref;
BOOL bIsPopup = (flags & TPM_POPUPMENU) != 0;
TRACE("owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x\n",
pwndOwner, menu, id, x, y);
TRACE("owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
pwndOwner, menu, id, x, y, xanchor, yanchor);
if (menu->iItem != NO_SELECTED_ITEM)
{
@ -2971,11 +2883,6 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl
menu->iItem = NO_SELECTED_ITEM;
}
#if SHOW_DEBUGRECT
if (pExclude)
DebugRect(pExclude, RGB(255, 0, 0));
#endif
menu->dwArrowsOn = 0;
MENU_PopupMenuCalcSize(menu, pwndOwner);
@ -2984,102 +2891,67 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl
width = menu->cxMenu + UserGetSystemMetrics(SM_CXBORDER);
height = menu->cyMenu + UserGetSystemMetrics(SM_CYBORDER);
if (flags & TPM_LAYOUTRTL)
/* FIXME: should use item rect */
pt.x = x;
pt.y = y;
monitor = UserMonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
if (flags & TPM_LAYOUTRTL)
flags ^= TPM_RIGHTALIGN;
if (flags & TPM_RIGHTALIGN)
x -= width;
if (flags & TPM_CENTERALIGN)
x -= width / 2;
if( flags & TPM_RIGHTALIGN ) x -= width;
if( flags & TPM_CENTERALIGN ) x -= width / 2;
if (flags & TPM_BOTTOMALIGN)
y -= height;
if (flags & TPM_VCENTERALIGN)
y -= height / 2;
if( flags & TPM_BOTTOMALIGN ) y -= height;
if( flags & TPM_VCENTERALIGN ) y -= height / 2;
/* FIXME: should use item rect */
ptx.x = x;
ptx.y = y;
#if SHOW_DEBUGRECT
DebugPoint(x, y, RGB(0, 0, 255));
#endif
monitor = UserMonitorFromPoint( ptx, MONITOR_DEFAULTTONEAREST );
/* We are off the right side of the screen */
if (x + width > monitor->rcMonitor.right)
if( x + width > monitor->rcMonitor.right)
{
if ((x - width) < monitor->rcMonitor.left || x >= monitor->rcMonitor.right)
x = monitor->rcMonitor.right - width;
else
x -= width;
}
if( xanchor && x >= width - xanchor )
x -= width - xanchor;
/* We are off the left side of the screen */
if (x < monitor->rcMonitor.left)
{
/* Re-orient the menu around the x-axis */
x += width;
if (x < monitor->rcMonitor.left || x >= monitor->rcMonitor.right || bIsPopup)
x = monitor->rcMonitor.left;
}
/* Same here, but then the top */
if (y < monitor->rcMonitor.top)
{
y += height;
if (y < monitor->rcMonitor.top || y >= monitor->rcMonitor.bottom || bIsPopup)
y = monitor->rcMonitor.top;
}
/* And the bottom */
if (y + height > monitor->rcMonitor.bottom)
{
if ((y - height) < monitor->rcMonitor.top || y >= monitor->rcMonitor.bottom || bIsPopup)
y = monitor->rcMonitor.bottom - height;
else
y -= height;
}
if (pExclude)
{
RECT Cleaned;
if (RECTL_bIntersectRect(&Cleaned, pExclude, &monitor->rcMonitor) &&
RECTL_Intersect(&Cleaned, x, y, width, height))
if( x + width > monitor->rcMonitor.right)
{
UINT flag_mods[] = {
0, /* First try the 'normal' way */
TPM_BOTTOMALIGN | TPM_RIGHTALIGN, /* Then try the opposite side */
TPM_VERTICAL, /* Then swap horizontal / vertical */
TPM_BOTTOMALIGN | TPM_RIGHTALIGN | TPM_VERTICAL, /* Then the other side again (still swapped hor/ver) */
};
UINT n;
for (n = 0; n < RTL_NUMBER_OF(flag_mods); ++n)
{
INT tx = x;
INT ty = y;
/* Try to move a bit around */
if (MENU_MoveRect(flags ^ flag_mods[n], &tx, &ty, width, height, &Cleaned, monitor) &&
!RECTL_Intersect(&Cleaned, tx, ty, width, height))
{
x = tx;
y = ty;
break;
}
}
/* If none worked, we go with the original x/y */
/* If we would flip around our origin, would we go off screen on the other side?
Or is our origin itself too far to the right already? */
if (x - width < monitor->rcMonitor.left || x > monitor->rcMonitor.right)
x = monitor->rcMonitor.right - width;
else
x -= width;
}
}
#if SHOW_DEBUGRECT
if( x < monitor->rcMonitor.left )
{
RECT rr = {x, y, x + width, y + height};
DebugRect(&rr, RGB(0, 255, 0));
/* If we would flip around our origin, would we go off screen on the other side? */
if (x + width > monitor->rcMonitor.right)
x = monitor->rcMonitor.left;
else
x += width;
}
if( y + height > monitor->rcMonitor.bottom)
{
if( yanchor && y >= height + yanchor )
y -= height + yanchor;
if( y + height > monitor->rcMonitor.bottom)
{
/* If we would flip around our origin, would we go off screen on the other side?
Or is our origin itself too far to the bottom already? */
if (y - height < monitor->rcMonitor.top || y > monitor->rcMonitor.bottom)
y = monitor->rcMonitor.bottom - height;
else
y -= height;
}
}
if( y < monitor->rcMonitor.top )
{
/* If we would flip around our origin, would we go off screen on the other side? */
if (y + height > monitor->rcMonitor.bottom)
y = monitor->rcMonitor.top;
else
y += height;
}
#endif
pWnd = ValidateHwndNoErr( menu->hWnd );
@ -3327,7 +3199,7 @@ static void FASTCALL MENU_HideSubPopups(PWND pWndOwner, PMENU Menu,
*/
static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFirst, UINT Flags)
{
RECT Rect, ParentRect;
RECT Rect;
ITEM *Item;
HDC Dc;
PWND pWnd;
@ -3362,13 +3234,6 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
pWnd = ValidateHwndNoErr(Menu->hWnd);
/* Grab the rect of our (entire) parent menu, so we can try to not overlap it */
if (!IntGetWindowRect(pWnd, &ParentRect))
{
ERR("No pWnd\n");
ParentRect = Rect;
}
/* correct item if modified as a reaction to WM_INITMENUPOPUP message */
if (!(Item->fState & MF_HILITE))
{
@ -3445,7 +3310,7 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
MENU_InitPopup( WndOwner, Item->spSubMenu, Flags );
MENU_ShowPopup( WndOwner, Item->spSubMenu, Menu->iItem, Flags,
Rect.left, Rect.top, &ParentRect);
Rect.left, Rect.top, Rect.right, Rect.bottom );
if (SelectFirst)
{
MENU_MoveSelection(WndOwner, Item->spSubMenu, ITEM_NEXT);
@ -4045,7 +3910,7 @@ static void FASTCALL MENU_KeyRight(MTRACKER *pmt, UINT Flags, UINT msg)
* Menu tracking code.
*/
static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
PWND pwnd)
PWND pwnd, const RECT *lprect )
{
MSG msg;
BOOL fRemove;
@ -4068,8 +3933,9 @@ static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
mt.Pt.x = x;
mt.Pt.y = y;
TRACE("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x\n",
UserHMGetHandle(pmenu), wFlags, x, y, UserHMGetHandle(pwnd));
TRACE("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n",
UserHMGetHandle(pmenu), wFlags, x, y, UserHMGetHandle(pwnd), lprect ? lprect->left : 0, lprect ? lprect->top : 0,
lprect ? lprect->right : 0, lprect ? lprect->bottom : 0);
pti->MessageQueue->QF_flags &= ~QF_ACTIVATIONCHANGE;
@ -4480,7 +4346,7 @@ VOID MENU_TrackMouseMenuBar( PWND pWnd, ULONG ht, POINT pt)
MENU_InitTracking(pWnd, pMenu, FALSE, wFlags);
/* fetch the window menu again, it may have changed */
pMenu = (ht == HTSYSMENU) ? get_win_sys_menu( UserHMGetHandle(pWnd) ) : IntGetMenu( UserHMGetHandle(pWnd) );
MENU_TrackMenu(pMenu, wFlags, pt.x, pt.y, pWnd);
MENU_TrackMenu(pMenu, wFlags, pt.x, pt.y, pWnd, NULL);
MENU_ExitTracking(pWnd, FALSE, wFlags);
}
}
@ -4544,7 +4410,7 @@ VOID MENU_TrackKbdMenuBar(PWND pwnd, UINT wParam, WCHAR wChar)
}
track_menu:
MENU_TrackMenu( TrackMenu, wFlags, 0, 0, pwnd );
MENU_TrackMenu( TrackMenu, wFlags, 0, 0, pwnd, NULL );
MENU_ExitTracking( pwnd, FALSE, wFlags);
}
@ -4586,8 +4452,9 @@ BOOL WINAPI IntTrackPopupMenuEx( PMENU menu, UINT wFlags, int x, int y,
if (menu->fFlags & MNF_SYSMENU)
MENU_InitSysMenuPopup( menu, pWnd->style, pWnd->pcls->style, HTSYSMENU);
if (MENU_ShowPopup(pWnd, menu, 0, wFlags | TPM_POPUPMENU, x, y, lpTpm ? &lpTpm->rcExclude : NULL))
ret = MENU_TrackMenu( menu, wFlags | TPM_POPUPMENU, 0, 0, pWnd);
if (MENU_ShowPopup(pWnd, menu, 0, wFlags, x, y, 0, 0 ))
ret = MENU_TrackMenu( menu, wFlags | TPM_POPUPMENU, 0, 0, pWnd,
lpTpm ? &lpTpm->rcExclude : NULL);
else
{
MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);