include/vcl/menu.hxx       |    5 +
 vcl/source/window/menu.cxx |  149 +++++++++++++++++++++++++--------------------
 2 files changed, 89 insertions(+), 65 deletions(-)

New commits:
commit fb9af884de622cdac23887417ccb32cfd34860c3
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Sat Nov 20 15:06:35 2021 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Jun 21 18:43:03 2022 +0200

    Refactor PopupMenu::ImplExecute for async support
    
    Splits ImplExecute into PrepareRun, Run and FinishRun.
    
    Change-Id: Ifddb1e968b468c9757eeece0bb19513cc26a9c8d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125597
    Tested-by: Jenkins
    Reviewed-by: Jan-Marek Glogowski <glo...@fbihome.de>

diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index 538cc4c88b80..bb0ef8cee6db 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -495,7 +495,10 @@ class VCL_DLLPUBLIC PopupMenu final : public Menu
 
 private:
     SAL_DLLPRIVATE MenuFloatingWindow * ImplGetFloatingWindow() const;
-    SAL_DLLPRIVATE sal_uInt16 ImplExecute( const VclPtr<vcl::Window>& pW, 
const tools::Rectangle& rRect, FloatWinPopupFlags nPopupModeFlags, Menu* 
pSFrom, bool bPreSelectFirst );
+    SAL_DLLPRIVATE bool PrepareRun(const VclPtr<vcl::Window>& pParentWin, 
tools::Rectangle& rRect, FloatWinPopupFlags& nPopupModeFlags, Menu* pSFrom, 
bool& bRealExecute, VclPtr<MenuFloatingWindow>&);
+    SAL_DLLPRIVATE bool Run(const VclPtr<MenuFloatingWindow>&, bool 
bRealExecute, bool bPreSelectFirst, FloatWinPopupFlags nPopupModeFlags, Menu* 
pSFrom, const tools::Rectangle& rRect);
+    SAL_DLLPRIVATE void FinishRun(const VclPtr<MenuFloatingWindow>&, const 
VclPtr<vcl::Window>& pParentWin, bool bRealExecute, bool bIsNativeMenu);
+    SAL_DLLPRIVATE sal_uInt16 ImplExecute(const VclPtr<vcl::Window>& 
pParentWin, const tools::Rectangle& rRect, FloatWinPopupFlags nPopupModeFlags, 
Menu* pSFrom, bool bPreSelectFirst);
     SAL_DLLPRIVATE void ImplFlushPendingSelect();
     SAL_DLLPRIVATE tools::Long ImplCalcHeight( sal_uInt16 nEntries ) const;
     SAL_DLLPRIVATE sal_uInt16 ImplCalcVisEntries( tools::Long nMaxHeight, 
sal_uInt16 nStartEntry, sal_uInt16* pLastVisible = nullptr ) const;
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index bd244319e136..9f680b9071c1 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -2740,10 +2740,8 @@ sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, 
const Point& rPopupPos
     return Execute( pExecWindow, tools::Rectangle( rPopupPos, rPopupPos ), 
PopupMenuFlags::ExecuteDown );
 }
 
-sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, const 
tools::Rectangle& rRect, PopupMenuFlags nFlags )
+static FloatWinPopupFlags lcl_TranslateFlags(PopupMenuFlags nFlags)
 {
-    ENSURE_OR_RETURN( pExecWindow, "PopupMenu::Execute: need a non-NULL 
window!", 0 );
-
     FloatWinPopupFlags nPopupModeFlags = FloatWinPopupFlags::NONE;
     if ( nFlags & PopupMenuFlags::ExecuteDown )
         nPopupModeFlags = FloatWinPopupFlags::Down;
@@ -2757,7 +2755,13 @@ sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, 
const tools::Rectangle&
     if (nFlags & PopupMenuFlags::NoMouseUpClose )                      // 
allow popup menus to stay open on mouse button up
         nPopupModeFlags |= FloatWinPopupFlags::NoMouseUpClose;    // useful if 
the menu was opened on mousebutton down (eg toolbox configuration)
 
-    return ImplExecute( pExecWindow, rRect, nPopupModeFlags, nullptr, false );
+    return nPopupModeFlags;
+}
+
+sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, const 
tools::Rectangle& rRect, PopupMenuFlags nFlags )
+{
+    ENSURE_OR_RETURN( pExecWindow, "PopupMenu::Execute: need a non-NULL 
window!", 0 );
+    return ImplExecute( pExecWindow, rRect, lcl_TranslateFlags(nFlags), 
nullptr, false );
 }
 
 void PopupMenu::ImplFlushPendingSelect()
@@ -2773,10 +2777,14 @@ void PopupMenu::ImplFlushPendingSelect()
     }
 }
 
-sal_uInt16 PopupMenu::ImplExecute( const VclPtr<vcl::Window>& pW, const 
tools::Rectangle& rRect, FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, bool 
bPreSelectFirst )
+bool PopupMenu::PrepareRun(const VclPtr<vcl::Window>& pParentWin, 
tools::Rectangle& rRect,
+                           FloatWinPopupFlags& nPopupModeFlags, Menu* pSFrom,
+                           bool& bRealExecute, VclPtr<MenuFloatingWindow>& 
pWin)
 {
-    if ( !pSFrom && ( vcl::IsInPopupMenuExecute() || !GetItemCount() ) )
-        return 0;
+    bRealExecute = false;
+    const sal_uInt16 nItemCount = GetItemCount();
+    if (!pSFrom && (vcl::IsInPopupMenuExecute() || !nItemCount))
+        return false;
 
     mpLayoutData.reset();
 
@@ -2788,7 +2796,6 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
     bCanceled = false;
 
     VclPtr<vcl::Window> xFocusId;
-    bool bRealExecute = false;
     if ( !pStartedFrom )
     {
         pSVData->mpWinData->mbNoDeactivate = true;
@@ -2804,25 +2811,24 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
     }
 
     SAL_WARN_IF( ImplGetWindow(), "vcl", "Win?!" );
-    tools::Rectangle aRect( rRect );
-    aRect.SetPos( pW->OutputToScreenPixel( aRect.TopLeft() ) );
+    rRect.SetPos(pParentWin->OutputToScreenPixel(rRect.TopLeft()));
 
+    nPopupModeFlags |= FloatWinPopupFlags::NoKeyClose | 
FloatWinPopupFlags::AllMouseButtonClose | FloatWinPopupFlags::GrabFocus;
     if (bRealExecute)
         nPopupModeFlags |= FloatWinPopupFlags::NewLevel;
-    nPopupModeFlags |= FloatWinPopupFlags::NoKeyClose | 
FloatWinPopupFlags::AllMouseButtonClose;
 
     bInCallback = true; // set it here, if Activate overridden
     Activate();
     bInCallback = false;
 
-    if ( pW->isDisposed() )
-        return 0;   // Error
+    if (pParentWin->isDisposed())
+        return false;
 
     if ( bCanceled || bKilled )
-        return 0;
+        return false;
 
-    if ( !GetItemCount() )
-        return 0;
+    if (!nItemCount)
+        return false;
 
     // The flag MenuFlags::HideDisabledEntries is inherited.
     if ( pSFrom )
@@ -2852,10 +2858,10 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
         ImplCallEventListeners(VclEventId::MenuSubmenuChanged, nPos);
     }
 
-    VclPtrInstance<MenuFloatingWindow> pWin( this, pW, WB_BORDER | 
WB_SYSTEMWINDOW );
+    pWin = VclPtrInstance<MenuFloatingWindow>(this, pParentWin, WB_BORDER | 
WB_SYSTEMWINDOW);
     if (comphelper::LibreOfficeKit::isActive() && get_id() == 
"editviewspellmenu")
     {
-        VclPtr<vcl::Window> xNotifierParent = pW->GetParentWithLOKNotifier();
+        VclPtr<vcl::Window> xNotifierParent = 
pParentWin->GetParentWithLOKNotifier();
         assert(xNotifierParent && xNotifierParent->GetLOKNotifier() && 
"editview menu without LOKNotifier");
         pWin->SetLOKNotifier(xNotifierParent->GetLOKNotifier());
     }
@@ -2874,9 +2880,9 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
         vcl::Window* pDeskW = pWindow->GetWindow( GetWindowType::RealParent );
         if( ! pDeskW )
             pDeskW = pWindow;
-        Point aDesktopTL( pDeskW->OutputToAbsoluteScreenPixel( aRect.TopLeft() 
) );
+        Point aDesktopTL(pDeskW->OutputToAbsoluteScreenPixel(rRect.TopLeft()));
         aDesktopRect = Application::GetScreenPosSizePixel(
-            Application::GetBestScreen( tools::Rectangle( aDesktopTL, 
aRect.GetSize() ) ));
+            Application::GetBestScreen(tools::Rectangle(aDesktopTL, 
rRect.GetSize())));
     }
 
     tools::Long nMaxHeight = aDesktopRect.GetHeight();
@@ -2891,8 +2897,8 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
         if ( pRef->GetParent() )
             pRef = pRef->GetParent();
 
-        tools::Rectangle devRect(  pRef->OutputToAbsoluteScreenPixel( 
aRect.TopLeft() ),
-                            pRef->OutputToAbsoluteScreenPixel( 
aRect.BottomRight() ) );
+        tools::Rectangle 
devRect(pRef->OutputToAbsoluteScreenPixel(rRect.TopLeft()),
+                                 
pRef->OutputToAbsoluteScreenPixel(rRect.BottomRight()));
 
         tools::Long nHeightAbove = devRect.Top() - aDesktopRect.Top();
         tools::Long nHeightBelow = aDesktopRect.Bottom() - devRect.Bottom();
@@ -2907,7 +2913,7 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
     nMaxHeight = std::max(nMaxHeight, tools::Long(768));
 
     if (pStartedFrom && pStartedFrom->IsMenuBar())
-        nMaxHeight -= pW->GetSizePixel().Height();
+        nMaxHeight -= pParentWin->GetSizePixel().Height();
     sal_Int32 nLeft, nTop, nRight, nBottom;
     pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
     nMaxHeight -= nTop+nBottom;
@@ -2919,43 +2925,34 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
         aSz.setHeight( ImplCalcHeight( nEntries ) );
     }
 
-    // tdf#126054 hold this until after function completes
-    VclPtr<PopupMenu> xThis(this);
-
     pWin->SetFocusId( xFocusId );
     pWin->SetOutputSizePixel( aSz );
-    if ( GetItemCount() )
+    return true;
+}
+
+bool PopupMenu::Run(const VclPtr<MenuFloatingWindow>& pWin, const bool 
bRealExecute, const bool bPreSelectFirst,
+                    const FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, 
const tools::Rectangle& rRect)
+{
+    SalMenu* pMenu = ImplGetSalMenu();
+    if (pMenu && bRealExecute && pMenu->ShowNativePopupMenu(pWin, rRect, 
nPopupModeFlags))
+        return true;
+
+    pWin->StartPopupMode(rRect, nPopupModeFlags);
+    if (pSFrom)
     {
-        SalMenu* pMenu = ImplGetSalMenu();
-        if( pMenu && bRealExecute && pMenu->ShowNativePopupMenu( pWin, aRect, 
nPopupModeFlags | FloatWinPopupFlags::GrabFocus ) )
-        {
-            pWin->StopExecute();
-            pWin->doShutdown();
-            pWindow.disposeAndClear();
-            ImplClosePopupToolBox(pW);
-            ImplFlushPendingSelect();
-            return nSelectedId;
-        }
+        sal_uInt16 aPos;
+        if (pSFrom->IsMenuBar())
+            aPos = static_cast<MenuBarWindow 
*>(pSFrom->pWindow.get())->GetHighlightedItem();
         else
-        {
-            pWin->StartPopupMode( aRect, nPopupModeFlags | 
FloatWinPopupFlags::GrabFocus );
-        }
-        if( pSFrom )
-        {
-            sal_uInt16 aPos;
-            if (pSFrom->IsMenuBar())
-                aPos = static_cast<MenuBarWindow 
*>(pSFrom->pWindow.get())->GetHighlightedItem();
-            else
-                aPos = static_cast<MenuFloatingWindow 
*>(pSFrom->pWindow.get())->GetHighlightedItem();
+            aPos = static_cast<MenuFloatingWindow 
*>(pSFrom->pWindow.get())->GetHighlightedItem();
 
-            pWin->SetPosInParent( aPos );  // store position to be sent in 
SUBMENUDEACTIVATE
-            pSFrom->ImplCallEventListeners( VclEventId::MenuSubmenuActivate, 
aPos );
-        }
+        pWin->SetPosInParent(aPos);  // store position to be sent in 
SUBMENUDEACTIVATE
+        pSFrom->ImplCallEventListeners(VclEventId::MenuSubmenuActivate, aPos);
     }
+
     if ( bPreSelectFirst )
     {
-        size_t nCount = pItemList->size();
-        for ( size_t n = 0; n < nCount; n++ )
+        for (size_t n = 0; n < static_cast<size_t>(GetItemCount()); n++)
         {
             MenuItemData* pData = pItemList->GetDataFromPos( n );
             if (  (  pData->bEnabled
@@ -2966,22 +2963,30 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
                && ImplIsSelectable( n )
                )
             {
-                pWin->ChangeHighlightItem( n, false );
+                pWin->ChangeHighlightItem(n, false);
                 break;
             }
         }
     }
-    if ( bRealExecute )
-    {
+
+    if (bRealExecute)
         pWin->Execute();
-        if (pWin->isDisposed())
-            return 0;
 
-        xFocusId = pWin->GetFocusId();
+    return false;
+}
+
+void PopupMenu::FinishRun(const VclPtr<MenuFloatingWindow>& pWin, const 
VclPtr<vcl::Window>& pParentWin, const bool bRealExecute, const bool 
bIsNativeMenu)
+{
+    if (!bRealExecute || pWin->isDisposed())
+        return;
+
+    if (!bIsNativeMenu)
+    {
+        VclPtr<vcl::Window> xFocusId = pWin->GetFocusId();
         assert(xFocusId == nullptr && "Focus should already be restored by 
MenuFloatingWindow::End");
         pWin->ImplEndPopupMode(FloatWinPopupEndFlags::NONE, xFocusId);
 
-        if ( nSelectedId )  // then clean up .. ( otherwise done by TH )
+        if (nSelectedId)  // then clean up .. ( otherwise done by TH )
         {
             PopupMenu* pSub = pWin->GetActivePopup();
             while ( pSub )
@@ -2990,13 +2995,29 @@ sal_uInt16 PopupMenu::ImplExecute( const 
VclPtr<vcl::Window>& pW, const tools::R
                 pSub = pSub->ImplGetFloatingWindow()->GetActivePopup();
             }
         }
-        pWin->doShutdown();
-        pWindow.disposeAndClear();
-        ImplClosePopupToolBox(pW);
-        ImplFlushPendingSelect();
     }
+    else
+        pWin->StopExecute();
 
-    return bRealExecute ? nSelectedId : 0;
+    pWin->doShutdown();
+    pWindow.disposeAndClear();
+    ImplClosePopupToolBox(pParentWin);
+    ImplFlushPendingSelect();
+}
+
+sal_uInt16 PopupMenu::ImplExecute(const VclPtr<vcl::Window>& pParentWin, const 
tools::Rectangle& rRect,
+                                  FloatWinPopupFlags nPopupModeFlags, Menu* 
pSFrom, bool bPreSelectFirst)
+{
+    // tdf#126054 hold this until after function completes
+    VclPtr<PopupMenu> xThis(this);
+    bool bRealExecute = false;
+    tools::Rectangle aRect(rRect);
+    VclPtr<MenuFloatingWindow> pWin;
+    if (!PrepareRun(pParentWin, aRect, nPopupModeFlags, pSFrom, bRealExecute, 
pWin))
+        return 0;
+    const bool bNative = Run(pWin, bRealExecute, bPreSelectFirst, 
nPopupModeFlags, pSFrom, aRect);
+    FinishRun(pWin, pParentWin, bRealExecute, bNative);
+    return nSelectedId;
 }
 
 sal_uInt16 PopupMenu::ImplCalcVisEntries( tools::Long nMaxHeight, sal_uInt16 
nStartEntry, sal_uInt16* pLastVisible ) const

Reply via email to