https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7c45a646e9673f71b1d2ae2c36755094775e8685

commit 7c45a646e9673f71b1d2ae2c36755094775e8685
Author:     Mark Jansen <[email protected]>
AuthorDate: Sun Aug 4 23:47:02 2019 +0200
Commit:     Mark Jansen <[email protected]>
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 */
         }
     }
 

Reply via email to