mirror of
https://github.com/reactos/reactos.git
synced 2024-11-16 12:00:01 +00:00
[WIN32SS] Rewrite MENU_ShowPopup to take the exclude rectangle into account
CORE-15863
This commit is contained in:
parent
0f16d44b66
commit
a59df3858c
1 changed files with 147 additions and 50 deletions
|
@ -2860,16 +2860,57 @@ static BOOL MENU_InitPopup( PWND pWndOwner, PMENU menu, UINT flags )
|
||||||
return TRUE;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MenuShowPopup
|
* MenuShowPopup
|
||||||
*
|
*
|
||||||
* Display a popup menu.
|
* Display a popup menu.
|
||||||
*/
|
*/
|
||||||
static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT flags,
|
static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT flags,
|
||||||
INT x, INT y)
|
INT x, INT y, const RECT* pExclude)
|
||||||
{
|
{
|
||||||
UINT width, height;
|
UINT width, height;
|
||||||
POINT pt;
|
POINT ptx;
|
||||||
PMONITOR monitor;
|
PMONITOR monitor;
|
||||||
PWND pWnd;
|
PWND pWnd;
|
||||||
USER_REFERENCE_ENTRY Ref;
|
USER_REFERENCE_ENTRY Ref;
|
||||||
|
@ -2884,6 +2925,11 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl
|
||||||
menu->iItem = NO_SELECTED_ITEM;
|
menu->iItem = NO_SELECTED_ITEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SHOW_DEBUGRECT
|
||||||
|
if (pExclude)
|
||||||
|
DebugRect(pExclude, RGB(255, 0, 0));
|
||||||
|
#endif
|
||||||
|
|
||||||
menu->dwArrowsOn = 0;
|
menu->dwArrowsOn = 0;
|
||||||
MENU_PopupMenuCalcSize(menu, pwndOwner);
|
MENU_PopupMenuCalcSize(menu, pwndOwner);
|
||||||
|
|
||||||
|
@ -2892,61 +2938,106 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl
|
||||||
width = menu->cxMenu + UserGetSystemMetrics(SM_CXBORDER);
|
width = menu->cxMenu + UserGetSystemMetrics(SM_CXBORDER);
|
||||||
height = menu->cyMenu + UserGetSystemMetrics(SM_CYBORDER);
|
height = menu->cyMenu + UserGetSystemMetrics(SM_CYBORDER);
|
||||||
|
|
||||||
/* FIXME: should use item rect */
|
|
||||||
pt.x = x;
|
|
||||||
pt.y = y;
|
|
||||||
monitor = UserMonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
|
|
||||||
|
|
||||||
if (flags & TPM_LAYOUTRTL)
|
if (flags & TPM_LAYOUTRTL)
|
||||||
flags ^= TPM_RIGHTALIGN;
|
flags ^= TPM_RIGHTALIGN;
|
||||||
|
|
||||||
if( flags & TPM_RIGHTALIGN ) x -= width;
|
if (flags & TPM_RIGHTALIGN)
|
||||||
if( flags & TPM_CENTERALIGN ) x -= width / 2;
|
x -= width;
|
||||||
|
if (flags & TPM_CENTERALIGN)
|
||||||
|
x -= width / 2;
|
||||||
|
|
||||||
if( flags & TPM_BOTTOMALIGN ) y -= height;
|
if (flags & TPM_BOTTOMALIGN)
|
||||||
if( flags & TPM_VCENTERALIGN ) y -= height / 2;
|
y -= height;
|
||||||
|
if (flags & TPM_VCENTERALIGN)
|
||||||
|
y -= height / 2;
|
||||||
|
|
||||||
if( x + width > monitor->rcMonitor.right)
|
/* 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 || bIsPopup)
|
||||||
{
|
|
||||||
/* 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 (!bIsPopup || x - width < monitor->rcMonitor.left || x > monitor->rcMonitor.right)
|
|
||||||
x = monitor->rcMonitor.right - width;
|
x = monitor->rcMonitor.right - width;
|
||||||
else
|
else
|
||||||
x -= width;
|
x -= width;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if( x < monitor->rcMonitor.left )
|
/* We are off the left side of the screen */
|
||||||
|
if (x < monitor->rcMonitor.left)
|
||||||
{
|
{
|
||||||
/* If we would flip around our origin, would we go off screen on the other side? */
|
/* Re-orient the menu around the x-axis */
|
||||||
if (!bIsPopup || x + width > monitor->rcMonitor.right)
|
|
||||||
x = monitor->rcMonitor.left;
|
|
||||||
else
|
|
||||||
x += width;
|
x += width;
|
||||||
|
|
||||||
|
if (x < monitor->rcMonitor.left || x >= monitor->rcMonitor.right || bIsPopup)
|
||||||
|
x = monitor->rcMonitor.left;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y + height > monitor->rcMonitor.bottom)
|
/* Same here, but then the top */
|
||||||
|
if (y < monitor->rcMonitor.top)
|
||||||
{
|
{
|
||||||
if( y + height > monitor->rcMonitor.bottom)
|
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 we would flip around our origin, would we go off screen on the other side?
|
if ((y - height) < monitor->rcMonitor.top || y >= monitor->rcMonitor.bottom || bIsPopup)
|
||||||
Or is our origin itself too far to the bottom already? */
|
|
||||||
if (!bIsPopup || y - height < monitor->rcMonitor.top || y > monitor->rcMonitor.bottom)
|
|
||||||
y = monitor->rcMonitor.bottom - height;
|
y = monitor->rcMonitor.bottom - height;
|
||||||
else
|
else
|
||||||
y -= height;
|
y -= height;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if( y < monitor->rcMonitor.top )
|
if (pExclude || bIsPopup)
|
||||||
{
|
{
|
||||||
/* If we would flip around our origin, would we go off screen on the other side? */
|
RECT PopupOrigin = {x-1, y-1, x+1, y+1};
|
||||||
if (!bIsPopup || y + height > monitor->rcMonitor.bottom)
|
RECT Cleaned;
|
||||||
y = monitor->rcMonitor.top;
|
|
||||||
else
|
if (RECTL_bIntersectRect(&Cleaned, pExclude ? pExclude : &PopupOrigin, &monitor->rcMonitor) &&
|
||||||
y += height;
|
RECTL_Intersect(&Cleaned, x, y, width, height))
|
||||||
|
{
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
y = Cleaned.top - height;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
y = Cleaned.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Move in the horizontal direction: TPM_RIGHTALIGN means drop it to the left, otherways go right */
|
||||||
|
if (flags & TPM_RIGHTALIGN)
|
||||||
|
{
|
||||||
|
x = Cleaned.left - width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = Cleaned.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SHOW_DEBUGRECT
|
||||||
|
{
|
||||||
|
RECT rr = {x, y, x + width, y + height};
|
||||||
|
DebugRect(&rr, RGB(0, 255, 0));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pWnd = ValidateHwndNoErr( menu->hWnd );
|
pWnd = ValidateHwndNoErr( menu->hWnd );
|
||||||
|
|
||||||
|
@ -3194,7 +3285,7 @@ static void FASTCALL MENU_HideSubPopups(PWND pWndOwner, PMENU Menu,
|
||||||
*/
|
*/
|
||||||
static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFirst, UINT Flags)
|
static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFirst, UINT Flags)
|
||||||
{
|
{
|
||||||
RECT Rect;
|
RECT Rect, ParentRect;
|
||||||
ITEM *Item;
|
ITEM *Item;
|
||||||
HDC Dc;
|
HDC Dc;
|
||||||
PWND pWnd;
|
PWND pWnd;
|
||||||
|
@ -3229,6 +3320,14 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
|
||||||
|
|
||||||
pWnd = ValidateHwndNoErr(Menu->hWnd);
|
pWnd = ValidateHwndNoErr(Menu->hWnd);
|
||||||
|
|
||||||
|
ParentRect = Rect;
|
||||||
|
if (pWnd)
|
||||||
|
{
|
||||||
|
POINT pt = {0, 0};
|
||||||
|
IntClientToScreen(pWnd, &pt);
|
||||||
|
RECTL_vOffsetRect(&ParentRect, pt.x, pt.y);
|
||||||
|
}
|
||||||
|
|
||||||
/* correct item if modified as a reaction to WM_INITMENUPOPUP message */
|
/* correct item if modified as a reaction to WM_INITMENUPOPUP message */
|
||||||
if (!(Item->fState & MF_HILITE))
|
if (!(Item->fState & MF_HILITE))
|
||||||
{
|
{
|
||||||
|
@ -3305,7 +3404,7 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
|
||||||
MENU_InitPopup( WndOwner, Item->spSubMenu, Flags );
|
MENU_InitPopup( WndOwner, Item->spSubMenu, Flags );
|
||||||
|
|
||||||
MENU_ShowPopup( WndOwner, Item->spSubMenu, Menu->iItem, Flags,
|
MENU_ShowPopup( WndOwner, Item->spSubMenu, Menu->iItem, Flags,
|
||||||
Rect.left, Rect.top);
|
Rect.left, Rect.top, &ParentRect);
|
||||||
if (SelectFirst)
|
if (SelectFirst)
|
||||||
{
|
{
|
||||||
MENU_MoveSelection(WndOwner, Item->spSubMenu, ITEM_NEXT);
|
MENU_MoveSelection(WndOwner, Item->spSubMenu, ITEM_NEXT);
|
||||||
|
@ -3905,7 +4004,7 @@ static void FASTCALL MENU_KeyRight(MTRACKER *pmt, UINT Flags, UINT msg)
|
||||||
* Menu tracking code.
|
* Menu tracking code.
|
||||||
*/
|
*/
|
||||||
static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
|
static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
|
||||||
PWND pwnd, const RECT *lprect )
|
PWND pwnd)
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
||||||
BOOL fRemove;
|
BOOL fRemove;
|
||||||
|
@ -3928,9 +4027,8 @@ static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
|
||||||
mt.Pt.x = x;
|
mt.Pt.x = x;
|
||||||
mt.Pt.y = y;
|
mt.Pt.y = y;
|
||||||
|
|
||||||
TRACE("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n",
|
TRACE("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x\n",
|
||||||
UserHMGetHandle(pmenu), wFlags, x, y, UserHMGetHandle(pwnd), lprect ? lprect->left : 0, lprect ? lprect->top : 0,
|
UserHMGetHandle(pmenu), wFlags, x, y, UserHMGetHandle(pwnd));
|
||||||
lprect ? lprect->right : 0, lprect ? lprect->bottom : 0);
|
|
||||||
|
|
||||||
pti->MessageQueue->QF_flags &= ~QF_ACTIVATIONCHANGE;
|
pti->MessageQueue->QF_flags &= ~QF_ACTIVATIONCHANGE;
|
||||||
|
|
||||||
|
@ -4341,7 +4439,7 @@ VOID MENU_TrackMouseMenuBar( PWND pWnd, ULONG ht, POINT pt)
|
||||||
MENU_InitTracking(pWnd, pMenu, FALSE, wFlags);
|
MENU_InitTracking(pWnd, pMenu, FALSE, wFlags);
|
||||||
/* fetch the window menu again, it may have changed */
|
/* fetch the window menu again, it may have changed */
|
||||||
pMenu = (ht == HTSYSMENU) ? get_win_sys_menu( UserHMGetHandle(pWnd) ) : IntGetMenu( UserHMGetHandle(pWnd) );
|
pMenu = (ht == HTSYSMENU) ? get_win_sys_menu( UserHMGetHandle(pWnd) ) : IntGetMenu( UserHMGetHandle(pWnd) );
|
||||||
MENU_TrackMenu(pMenu, wFlags, pt.x, pt.y, pWnd, NULL);
|
MENU_TrackMenu(pMenu, wFlags, pt.x, pt.y, pWnd);
|
||||||
MENU_ExitTracking(pWnd, FALSE, wFlags);
|
MENU_ExitTracking(pWnd, FALSE, wFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4405,7 +4503,7 @@ VOID MENU_TrackKbdMenuBar(PWND pwnd, UINT wParam, WCHAR wChar)
|
||||||
}
|
}
|
||||||
|
|
||||||
track_menu:
|
track_menu:
|
||||||
MENU_TrackMenu( TrackMenu, wFlags, 0, 0, pwnd, NULL );
|
MENU_TrackMenu( TrackMenu, wFlags, 0, 0, pwnd );
|
||||||
MENU_ExitTracking( pwnd, FALSE, wFlags);
|
MENU_ExitTracking( pwnd, FALSE, wFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4447,9 +4545,8 @@ BOOL WINAPI IntTrackPopupMenuEx( PMENU menu, UINT wFlags, int x, int y,
|
||||||
if (menu->fFlags & MNF_SYSMENU)
|
if (menu->fFlags & MNF_SYSMENU)
|
||||||
MENU_InitSysMenuPopup( menu, pWnd->style, pWnd->pcls->style, HTSYSMENU);
|
MENU_InitSysMenuPopup( menu, pWnd->style, pWnd->pcls->style, HTSYSMENU);
|
||||||
|
|
||||||
if (MENU_ShowPopup(pWnd, menu, 0, wFlags | TPM_POPUPMENU, x, y))
|
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,
|
ret = MENU_TrackMenu( menu, wFlags | TPM_POPUPMENU, 0, 0, pWnd);
|
||||||
lpTpm ? &lpTpm->rcExclude : NULL);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);
|
MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);
|
||||||
|
|
Loading…
Reference in a new issue