https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7c45a646e9673f71b1d2ae...
commit 7c45a646e9673f71b1d2ae2c36755094775e8685 Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Sun Aug 4 23:47:02 2019 +0200 Commit: Mark Jansen mark.jansen@reactos.org CommitDate: Tue Aug 6 21:17:47 2019 +0200
[WIN32SS] Iteratively mutate menu flags until we find a 'best fit' CORE-15863 --- win32ss/user/ntuser/menu.c | 92 +++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 25 deletions(-)
diff --git a/win32ss/user/ntuser/menu.c b/win32ss/user/ntuser/menu.c index c73151427c6..7bf7bbd97ae 100644 --- a/win32ss/user/ntuser/menu.c +++ b/win32ss/user/ntuser/menu.c @@ -2901,6 +2901,52 @@ static BOOL RECTL_Intersect(const RECT* pRect, INT x, INT y, UINT width, UINT he 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 * @@ -2962,7 +3008,7 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl /* We are off the right side of the screen */ if (x + width > monitor->rcMonitor.right) { - if ((x - width) < monitor->rcMonitor.left || x >= monitor->rcMonitor.right || bIsPopup) + if ((x - width) < monitor->rcMonitor.left || x >= monitor->rcMonitor.right) x = monitor->rcMonitor.right - width; else x -= width; @@ -2996,39 +3042,35 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl y -= height; }
- if (pExclude || bIsPopup) + if (pExclude) { - RECT PopupOrigin = {x-1, y-1, x+1, y+1}; RECT Cleaned;
- if (RECTL_bIntersectRect(&Cleaned, pExclude ? pExclude : &PopupOrigin, &monitor->rcMonitor) && + if (RECTL_bIntersectRect(&Cleaned, pExclude, &monitor->rcMonitor) && 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 + 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) { - /* 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 + 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 = Cleaned.right; + x = tx; + y = ty; + break; } } + /* If none worked, we go with the original x/y */ } }