[Libreoffice-commits] core.git: Branch 'feature/wasm' - 718 commits - accessibility/source android/Bootstrap android/default-document android/Makefile android/source avmedia/source basctl/source basegfx/source basic/inc basic/Library_sb.mk basic/qa basic/source binaryurp/qa bin/find-unneeded-includes bin/run bin/sanitize-excludelist.txt bridges/source canvas/source chart2/inc chart2/IwyuFilter_chart2.yaml chart2/Library_chartcore.mk chart2/qa chart2/source codemaker/source comphelper/qa comphelper/source compilerplugins/clang config_host.mk.in configmgr/source configure.ac connectivity/source cppuhelper/source cppu/source cpputools/source cui/inc cui/qa cui/source cui/uiconfig dbaccess/qa dbaccess/source desktop/inc desktop/qa desktop/scripts desktop/source dictionaries download.lst drawinglayer/README.md drawinglayer/source editeng/inc editeng/qa editeng/source emfio/inc emfio/qa emfio/README.md emfio/source eventattacher/README.md extensions/source external/cairo external/cppunit external/fireb ird external/fontconfig external/freetype external/gpgmepp external/harfbuzz external/hsqldb external/hunspell external/hyphen external/icu external/lcms2 external/libabw external/libassuan external/libatomic_ops external/libcdr external/libebook external/libepubgen external/libetonyek external/libexttextcat external/libfreehand external/libgpg-error external/liblangtag external/libmspub external/libmwaw external/libnumbertext external/libodfgen external/liborcus external/libpagemaker external/libqxp external/librevenge external/libstaroffice external/libvisio external/libwebp external/libwpd external/libwpg external/libwps external/libxml2 external/libzmf external/lpsolve external/mythes external/nss external/openldap external/redland external/xmlsec external/zlib extras/source filter/CppunitTest_filter_textfilterdetect.mk filter/qa filter/source forms/source fpicker/source framework/inc framework/source .gitignore helpcontent2 hwpfilter/source i18nlangtag/source i18npool/inc i18np ool/qa i18npool/source i18nutil/source icon-themes/colibre icon-themes/colibre_dark icon-themes/colibre_dark_svg icon-themes/colibre_svg idlc/inc idlc/source idl/source include/basegfx include/basic include/comphelper include/connectivity include/editeng include/filter include/framework include/i18nutil include/jvmaccess include/LibreOfficeKit include/linguistic include/o3tl include/oox include/rtl include/sal include/sax include/sfx2 include/svl include/svtools include/svx include/toolkit include/tools include/unotools include/vcl include/xmloff io/source jvmaccess/source jvmfwk/inc jvmfwk/plugins jvmfwk/source l10ntools/inc l10ntools/source librelogo/source libreofficekit/source linguistic/source lotuswordpro/source Makefile.in o3tl/qa odk/CustomTarget_check.mk odk/docs odk/examples odk/index.html odk/index_online.html odk/Package_examples.mk odk/settings odk/source odk/util offapi/com offapi/UnoApi_offapi.mk officecfg/registry oox/inc oox/Library_oox.mk oox/qa oox/source opencl/s ource package/inc package/source pyuno/source README.md registry/source reportdesign/inc reportdesign/source Repository.mk RepositoryModule_host.mk sal/cppunittester sal/CppunitTest_sal_rtl.mk sal/inc sal/Library_cppunitmain.mk sal/Module_sal.mk sal/osl sal/qa sal/rtl sax/source sc/CppunitTest_sc_sparkline_test.mk schema/libreoffice sc/inc sc/Library_scfilt.mk sc/Library_sc.mk sc/qa scripting/source sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk sdext/source sd/qa sd/source sd/uiconfig setup_native/source sfx2/inc sfx2/source shell/Library_jumplist.mk shell/Module_shell.mk shell/source slideshow/source solenv/bin solenv/clang-format solenv/CompilerTest_compilerplugins_clang.mk solenv/flatpak-manifest.in solenv/gbuild starmath/inc starmath/source static/CustomTarget_emscripten_fs_image.mk static/emscripten static/README.wasm.md stoc/source svgio/source svl/source svtools/source svx/inc svx/qa svx/sdi svx/source sw/CppunitTest_sw_core_attr.mk sw/inc sw/layoutwriter_setup.mk sw/Libr ary_sw.mk sw/Module_sw.mk sw/qa sw/rtfexport_setup.mk sw/sdi sw/source sw/uiconfig sw/UITest_sw_fieldDialog.mk test/qa test/source testtools/IwyuFilter_testtools.yaml testtools/source toolkit/inc toolkit/IwyuFilter_toolkit.yaml toolkit/qa toolkit/source tools/CppunitTest_tools_test.mk tools/IwyuFilter_tools.yaml tools/qa tools/source translations ucb/CppunitTest_ucb_webdav_core.mk ucbhelper/IwyuFilter_ucbhelper.yaml ucbhelper/source ucb/IwyuFilter_ucb.yaml ucb/Library_ucpdav1.mk ucb/Module_ucb.mk ucb/README.md ucb/source UnoControls/inc UnoControls/IwyuFilter_UnoControls.yaml UnoControls/source unodevtools/inc unodevtools/IwyuFilter_unodevtools.yaml unodevtools/source unoidl/Module_unoidl.mk unoidl/source unotools/IwyuFilter_unotools.yaml unotools/source unoxml/qa unoxml/source uui/inc uui/source vbahelper/source vcl/CppunitTest_vcl_filter_ipdf.mk vcl/headless vcl/inc vcl/jsdialog vcl/Library_vclplug_gen.mk vcl/Library_vclplug_gtk4.mk vcl/osx vcl/qa vcl/qt5 vcl/skia vcl/source vcl/u nx vcl/win vcl/workben wizards/source writerfilter/CppunitTest_writerfilter_dmapper.mk writerfilter/qa writerfilter/source writerperfect/qa xmlhelp/source xmloff/inc xmloff/Library_xo.mk xmloff/qa xmloff/source xmlsecurity/inc xmlsecurity/source

Tue, 26 Apr 2022 09:16:03 -0700

Rebased ref, commits from common ancestor:
commit bfb3a2466a2fa627551b0af483c59430aa966e49
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Tue Apr 26 18:11:55 2022 +0200
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Apr 26 18:12:52 2022 +0200

    WASM HACK fix NEH build
    
    Workaround a toolchain bug. Also see comment in ~Desktop().
    
    Change-Id: I158877b78794d81ccdc74e4d5fc023e2061c1d96

diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx
index 3372e751dbf1..8eb71d3b13b5 100644
--- a/desktop/inc/app.hxx
+++ b/desktop/inc/app.hxx
@@ -166,7 +166,7 @@ class Desktop final : public Application
         BootstrapStatus         m_aBootstrapStatus;
 
         std::unique_ptr<Lockfile> m_xLockfile;
-        Timer                   m_firstRunTimer;
+        Timer                   *m_firstRunTimer;
         std::thread             m_aUpdateThread;
 };
 
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index a45ce9f82a51..e61ee9653697 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -426,14 +426,16 @@ Desktop::Desktop()
     , m_bServicesRegistered(false)
     , m_aBootstrapError(BE_OK)
     , m_aBootstrapStatus(BS_OK)
-    , m_firstRunTimer( "desktop::Desktop m_firstRunTimer" )
+    , m_firstRunTimer(new Timer("desktop::Desktop m_firstRunTimer"))
 {
-    m_firstRunTimer.SetTimeout(3000); // 3 sec.
-    m_firstRunTimer.SetInvokeHandler(LINK(this, Desktop, AsyncInitFirstRun));
+    m_firstRunTimer->SetTimeout(3000); // 3 sec.
+    m_firstRunTimer->SetInvokeHandler(LINK(this, Desktop, AsyncInitFirstRun));
 }
 
 Desktop::~Desktop()
 {
+// Uncommenting this delete breaks the WASM output with a runtime error
+//    delete m_firstRunTimer;
 }
 
 void Desktop::Init()
@@ -2556,7 +2558,7 @@ void Desktop::CheckFirstRun( )
 
     // use VCL timer, which won't trigger during shutdown if the
     // application exits before timeout
-    m_firstRunTimer.Start();
+    m_firstRunTimer->Start();
 
 #ifdef _WIN32
     // Check if Quickstarter should be started (on Windows only)
diff --git a/external/redland/ExternalProject_raptor.mk 
b/external/redland/ExternalProject_raptor.mk
index 324d231c5073..b3ae74c10b61 100644
--- a/external/redland/ExternalProject_raptor.mk
+++ b/external/redland/ExternalProject_raptor.mk
@@ -26,7 +26,7 @@ $(call gb_ExternalProject_get_state_target,raptor,build):
                LDFLAGS=" \
                        $(if $(filter LINUX 
FREEBSD,$(OS)),-Wl$(COMMA)-z$(COMMA)origin 
-Wl$(COMMA)-rpath$(COMMA)\\"\$$\$$ORIGIN") \
                        $(if $(SYSBASE),$(if $(filter LINUX 
SOLARIS,$(OS)),-L$(SYSBASE)/lib -L$(SYSBASE)/usr/lib -lpthread -ldl))" \
-               CPPFLAGS="$(if $(SYSBASE),-I$(SYSBASE)/usr/include)" \
+               CPPFLAGS="$(if $(SYSBASE),-I$(SYSBASE)/usr/include) 
$(gb_EMSCRIPTEN_CPPFLAGS)" \
                $(gb_RUN_CONFIGURE) ./configure --disable-gtk-doc \
                         --enable-parsers="rdfxml ntriples turtle trig guess 
rss-tag-soup" \
                        --with-www=xml \
diff --git a/external/redland/ExternalProject_rasqal.mk 
b/external/redland/ExternalProject_rasqal.mk
index dd8887c669c8..e7d1fdb1195d 100644
--- a/external/redland/ExternalProject_rasqal.mk
+++ b/external/redland/ExternalProject_rasqal.mk
@@ -22,7 +22,7 @@ $(eval $(call gb_ExternalProject_register_targets,rasqal,\
 $(call gb_ExternalProject_get_state_target,rasqal,build):
        $(call gb_Trace_StartRange,rasqal,EXTERNAL)
        $(call gb_ExternalProject_run,build,\
-               CFLAGS="$(CFLAGS) $(if $(filter 
TRUE,$(DISABLE_DYNLOADING)),-fvisibility=hidden) $(call 
gb_ExternalProject_get_build_flags,rasqal)" \
+               CFLAGS="$(CFLAGS) $(if $(filter 
TRUE,$(DISABLE_DYNLOADING)),-fvisibility=hidden) $(call 
gb_ExternalProject_get_build_flags,rasqal) $(gb_EMSCRIPTEN_CPPFLAGS)" \
                LDFLAGS=" \
                        $(if $(filter LINUX 
FREEBSD,$(OS)),-Wl$(COMMA)-z$(COMMA)origin 
-Wl$(COMMA)-rpath$(COMMA)\\"\$$\$$ORIGIN") \
                        $(if $(SYSBASE),$(if $(filter LINUX 
SOLARIS,$(OS)),-L$(SYSBASE)/lib -L$(SYSBASE)/usr/lib -lpthread -ldl))" \
diff --git a/external/redland/ExternalProject_redland.mk 
b/external/redland/ExternalProject_redland.mk
index d4dd34519670..d92c642b9cd1 100644
--- a/external/redland/ExternalProject_redland.mk
+++ b/external/redland/ExternalProject_redland.mk
@@ -23,7 +23,7 @@ $(eval $(call gb_ExternalProject_register_targets,redland,\
 $(call gb_ExternalProject_get_state_target,redland,build):
        $(call gb_Trace_StartRange,redland,EXTERNAL)
        $(call gb_ExternalProject_run,build,\
-               CFLAGS="$(CFLAGS) $(if $(filter 
TRUE,$(DISABLE_DYNLOADING)),-fvisibility=hidden) $(call 
gb_ExternalProject_get_build_flags,redland)" \
+               CFLAGS="$(CFLAGS) $(if $(filter 
TRUE,$(DISABLE_DYNLOADING)),-fvisibility=hidden) $(call 
gb_ExternalProject_get_build_flags,redland) $(gb_EMSCRIPTEN_CPPFLAGS)" \
                LDFLAGS=" \
                        $(if $(filter LINUX 
FREEBSD,$(OS)),-Wl$(COMMA)-z$(COMMA)origin 
-Wl$(COMMA)-rpath$(COMMA)\\"\$$\$$ORIGIN") \
                        $(if $(SYSBASE),$(if $(filter LINUX 
SOLARIS,$(OS)),-L$(SYSBASE)/lib -L$(SYSBASE)/usr/lib -lpthread -ldl))" \
commit c6d2fe585c343c8ac9f3395adf3443821174c1f6
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Sun Feb 20 14:06:54 2022 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Apr 26 18:12:28 2022 +0200

    fixme static tests
    
    Change-Id: I2aaffa032bd531272257ca40d6f9b9d25c4de5aa

diff --git a/sal/cppunittester/cppunittester.cxx 
b/sal/cppunittester/cppunittester.cxx
index 18773b2a67b6..63bc435cac99 100644
--- a/sal/cppunittester/cppunittester.cxx
+++ b/sal/cppunittester/cppunittester.cxx
@@ -244,6 +244,7 @@ public:
         , protectors(protectors_)
         , result(result_)
     {
+        (void) args_;
     }
     ProtectedFixtureFunctor(const ProtectedFixtureFunctor&) = delete;
     ProtectedFixtureFunctor& operator=(const ProtectedFixtureFunctor&) = 
delete;
commit 608cbb22b3e4d5544a5d8be76fda91e2eb367522
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Sun Jan 9 14:49:28 2022 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Apr 26 18:12:28 2022 +0200

    Add a larger Writer example document
    
    Change-Id: I4bc9a82c7f99563af8da62f889b51d1b583df760

diff --git a/android/default-document/example_larger.odt 
b/android/default-document/example_larger.odt
new file mode 100644
index 000000000000..1b3a1dfb877a
Binary files /dev/null and b/android/default-document/example_larger.odt differ
diff --git a/static/CustomTarget_emscripten_fs_image.mk 
b/static/CustomTarget_emscripten_fs_image.mk
index 8166802858e5..8c347de38d5a 100644
--- a/static/CustomTarget_emscripten_fs_image.mk
+++ b/static/CustomTarget_emscripten_fs_image.mk
@@ -1131,6 +1131,7 @@ gb_emscripten_fs_image_files := \
     $(INSTROOT)/$(LIBO_SHARE_RESOURCE_FOLDER)/common/fonts/opens___.ttf \
     $(INSTROOT)/$(LIBO_URE_ETC_FOLDER)/$(call gb_Helper_get_rcfile,uno) \
     $(INSTROOT)/$(LIBO_URE_MISC_FOLDER)/services.rdb \
+    $(SRCDIR)/android/default-document/example_larger.odt \
     $(SRCDIR)/android/default-document/example.odt \
 
 ifneq ($(ENABLE_WASM_STRIP_CHART),TRUE)
diff --git a/static/emscripten/soffice_args.js 
b/static/emscripten/soffice_args.js
index 7ecf7e8988e8..fa5e9dd4164d 100644
--- a/static/emscripten/soffice_args.js
+++ b/static/emscripten/soffice_args.js
@@ -2,5 +2,5 @@ Module['arguments'] = [
     '--norestore',
     '--nologo',
     '--writer',
-    '/android/default-document/example.odt'
+    '/android/default-document/example_larger.odt'
 ];
commit 6e205676339111aeef6fe478e51e049c66601684
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Wed Nov 17 01:57:33 2021 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Apr 26 18:12:28 2022 +0200

    WIP: async popup menus
    
    A first patch to get some feedback. Asnyc LO popup menus are still
    buggy, as I'm not sure where to call the PopupMenu::Finish for
    them.
    
    Also the XDialogClosedListener is currently just for convenience
    and might want some separate notifier.
    
    Fun fact, that ImplExecute / ImplPopup is called for submenu, but
    then doesn't execute. And generally the naming of some variables
    is IMHO wrong; I might also prefix Menu members with "m_" for
    easier readability.
    
    Change-Id: Id8b413aa6b4699201e58db0113649c6b224d33b6

diff --git a/include/sfx2/dispatch.hxx b/include/sfx2/dispatch.hxx
index ee445710b9c0..a1c0f9aa5ad2 100644
--- a/include/sfx2/dispatch.hxx
+++ b/include/sfx2/dispatch.hxx
@@ -20,6 +20,7 @@
 #define INCLUDED_SFX2_DISPATCH_HXX
 
 #include <memory>
+#include <functional>
 #include <sal/config.h>
 #include <sfx2/dllapi.h>
 #include <sfx2/toolbarids.hxx>
@@ -42,6 +43,7 @@ struct SfxDispatcher_Impl;
 
 namespace com::sun::star::awt { class XPopupMenu; }
 namespace vcl { class Window; }
+namespace com::sun::star::ui::dialogs { struct DialogClosedEvent; }
 
 enum class SfxDispatcherPopFlags
 {
@@ -136,8 +138,14 @@ public:
     SfxViewFrame*       GetFrame() const;
     SfxModule*          GetModule() const;
 
-    void                ExecutePopup( const OUString &rResName, vcl::Window 
*pWin = nullptr, const Point *pPos = nullptr );
-    static void         ExecutePopup( vcl::Window *pWin = nullptr, const Point 
*pPosPixel = nullptr );
+    /**
+     * @param rCloseFunc
+     *     If this is !nullptr, the popup will be just shown / run async and 
rCloseFunc will be called on close.
+     */
+    void ExecutePopup(const OUString &rResName, vcl::Window *pWin = nullptr, 
const Point *pPos = nullptr,
+                      const std::function<void(sal_Int16)>& rCloseFunc = 
nullptr);
+    static void ExecutePopup(vcl::Window *pWin = nullptr, const Point 
*pPosPixel = nullptr,
+                             const std::function<void(sal_Int16)>& rCloseFunc 
= nullptr);
 
     bool                IsAppDispatcher() const;
     bool                IsFlushed() const;
diff --git a/include/toolkit/awt/vclxmenu.hxx b/include/toolkit/awt/vclxmenu.hxx
index 096c370bce82..ffa89e9a8511 100644
--- a/include/toolkit/awt/vclxmenu.hxx
+++ b/include/toolkit/awt/vclxmenu.hxx
@@ -25,10 +25,11 @@
 #include <toolkit/helper/listenermultiplexer.hxx>
 
 #include <com/sun/star/awt/XMenuBar.hpp>
-#include <com/sun/star/awt/XPopupMenu.hpp>
+#include <com/sun/star/awt/XPopupMenuAsync.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/lang/XTypeProvider.hpp>
 #include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/ui/dialogs/XDialogClosedListener.hpp>
 
 #include <comphelper/servicehelper.hxx>
 #include <cppuhelper/weak.hxx>
@@ -39,6 +40,7 @@
 
 #include <vector>
 
+struct DialogClosedEvent;
 class Menu;
 class MenuBar;
 class PopupMenu;
@@ -51,10 +53,11 @@ typedef ::std::vector<
 typedef void (*MenuUserDataReleaseFunction)(void*);
 
 class TOOLKIT_DLLPUBLIC VCLXMenu :  public css::awt::XMenuBar,
-                                    public css::awt::XPopupMenu,
+                                    public css::awt::XPopupMenuAsync,
                                     public css::lang::XServiceInfo,
                                     public css::lang::XTypeProvider,
                                     public css::lang::XUnoTunnel,
+                                    public 
css::ui::dialogs::XDialogClosedListener,
                                     public ::cppu::OWeakObject
 {
 private:
@@ -76,7 +79,6 @@ public:
     VCLXMenu( Menu* pMenu );
     virtual ~VCLXMenu() override;
 
-
     Menu*    GetMenu() const { return mpMenu; }
     bool IsPopupMenu() const;
     void setUserValue(sal_uInt16 nItemId, void* nUserValue, 
MenuUserDataReleaseFunction aFunc);
@@ -137,10 +139,20 @@ public:
     virtual void SAL_CALL setItemImage( ::sal_Int16 nItemId, const 
css::uno::Reference< css::graphic::XGraphic >& xGraphic, sal_Bool bScale ) 
override;
     virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL 
getItemImage( ::sal_Int16 nItemId ) override;
 
+    // css::awt::XPopupMenuAsync
+    virtual sal_Bool SAL_CALL popup(const css::uno::Reference< 
css::awt::XWindowPeer >& Parent, const css::awt::Rectangle& Position,
+                                    ::sal_Int16 Direction, const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener) 
override;
+
     // css::lang::XServiceInfo
     virtual OUString SAL_CALL getImplementationName(  ) override;
     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) 
override;
     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  
) override;
+
+    // css::ui::dialogs::XDialogClosedListener
+    virtual void SAL_CALL dialogClosed(const 
css::ui::dialogs::DialogClosedEvent& aEvent) override;
+
+    // XEventListener (base of XDialogClosedListener)
+    virtual void SAL_CALL disposing(css::lang::EventObject const & Source) 
override;
 };
 
 class UNLESS_MERGELIBS(TOOLKIT_DLLPUBLIC) VCLXMenuBar final : public VCLXMenu
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index abad985775e4..4c91ac68d8f4 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -44,6 +44,7 @@ class Menu;
 class MenuItemList;
 class Image;
 class PopupMenu;
+struct PopupMenuFinishState;
 class KeyEvent;
 class MenuFloatingWindow;
 class SalMenu;
@@ -54,6 +55,7 @@ enum class FloatWinPopupFlags;
 enum class VclEventId;
 
 namespace com::sun::star::awt { class XPopupMenu; }
+namespace com::sun::star::ui::dialogs { class XDialogClosedListener; }
 namespace com::sun::star::accessibility { class XAccessible;  }
 
 namespace vcl
@@ -492,11 +494,16 @@ class VCL_DLLPUBLIC PopupMenu final : public Menu
     friend struct MenuItemData;
 
 private:
+    struct PopupMenuFinishState* m_pState;
+
     SAL_DLLPRIVATE MenuFloatingWindow * ImplGetFloatingWindow() const;
     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 bool Run(const VclPtr<MenuFloatingWindow>&, bool 
bRealExecute, bool bPreSelectFirst, FloatWinPopupFlags nPopupModeFlags, Menu* 
pSFrom, const tools::Rectangle& rRect,
+                            const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* xListener);
     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 bool ImplPopup(const VclPtr<vcl::Window>& pParentWin, const 
tools::Rectangle& rRect, FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, bool 
bPreSelectFirst,
+                                  const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>&);
     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;
@@ -519,6 +526,12 @@ public:
     sal_uInt16 Execute( vcl::Window* pWindow, const Point& rPopupPos );
     sal_uInt16 Execute( vcl::Window* pWindow, const tools::Rectangle& rRect, 
PopupMenuFlags nFlags = PopupMenuFlags::NONE );
 
+    bool Popup(vcl::Window* pParentWin, const Point& rPopupPos,
+               const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>&);
+    bool Popup(vcl::Window* pParentWin, const tools::Rectangle& rRect,
+               const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>&, PopupMenuFlags = 
PopupMenuFlags::NONE);
+    void Finish();
+
     // for the TestTool
     void EndExecute();
     virtual void SelectItem(sal_uInt16 nId) override;
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index a9b92639a667..7a77b02e98a7 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -1858,6 +1858,7 @@ $(eval $(call 
gb_UnoApi_add_idlfiles,offapi,com/sun/star/awt,\
        XPatternField \
        XPointer \
        XPopupMenu \
+       XPopupMenuAsync \
        XPrinter \
        XPrinterPropertySet \
        XPrinterServer \
diff --git a/offapi/com/sun/star/awt/XPopupMenuAsync.idl 
b/offapi/com/sun/star/awt/XPopupMenuAsync.idl
new file mode 100644
index 000000000000..d3f7b317f086
--- /dev/null
+++ b/offapi/com/sun/star/awt/XPopupMenuAsync.idl
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+#ifndef __com_sun_star_awt_XPopupMenuAsync_idl__
+#define __com_sun_star_awt_XPopupMenuAsync_idl__
+
+#include <com/sun/star/awt/XPopupMenu.idl>
+#include <com/sun/star/ui/dialogs/XDialogClosedListener.idl>
+
+module com {  module sun {  module star {  module awt {
+
+/** shows a pop-up menu without blocking.
+ */
+interface XPopupMenuAsync: XPopupMenu
+{
+    /** just shows the popup menu without blocking and calls the
+        XDialogClosedListener when closed,
+
+        @param Parent
+            the parent window.
+
+        @param Position
+            a Rectangle representing the coordinates system
+            where the popup menu should be executed.
+
+        @param Direction
+            the direction in which a popup menu will grow, as specified
+            by one of the PopupMenuDirection constants.
+
+        @param xListener
+            notified, if the popup is closed.
+
+        @return
+            returns true, if the popup has started to run async.
+            May fail, if the native backend doesn't implement async popups.
+    */
+    boolean popup([in] XWindowPeer Parent, [in] Rectangle Position, [in] short 
Direction,
+                  [in] ::com::sun::star::ui::dialogs::XDialogClosedListener 
xListener);
+};
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/view/drviews4.cxx b/sd/source/ui/view/drviews4.cxx
index b07279844265..548504af7746 100644
--- a/sd/source/ui/view/drviews4.cxx
+++ b/sd/source/ui/view/drviews4.cxx
@@ -800,7 +800,7 @@ void DrawViewShell::Command(const CommandEvent& rCEvt, 
::sd::Window* pWin)
             bool bShouldDisableEditHyperlink = ShouldDisableEditHyperlink();
 
             if(rCEvt.IsMouseEvent())
-                GetViewFrame()->GetDispatcher()->ExecutePopup( aPopupId );
+                GetViewFrame()->GetDispatcher()->ExecutePopup(aPopupId, 
nullptr, nullptr, [](sal_Int16){});
             else
             {
                 //don't open contextmenu at mouse position if not opened via 
mouse
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
index 17edf97cc16d..cce1d7d9ec19 100644
--- a/sfx2/source/control/dispatch.cxx
+++ b/sfx2/source/control/dispatch.cxx
@@ -60,6 +60,7 @@
 #include <svl/eitem.hxx>
 #include <svl/itemiter.hxx>
 #include <svl/itempool.hxx>
+#include <svtools/dialogclosedlistener.hxx>
 #include <toolkit/awt/vclxmenu.hxx>
 #include <toolkit/helper/vclunohelper.hxx>
 #include <tools/debug.hxx>
@@ -137,8 +138,12 @@ struct SfxDispatcher_Impl
     SfxDisableFlags      nDisableFlags;
     bool                 bFlushed;
     std::deque< std::deque<SfxToDo_Impl> > aToDoCopyStack;
+
+    static css::uno::Reference<css::frame::XPopupMenuController>* 
m_pActivePopupController;
 };
 
+css::uno::Reference<css::frame::XPopupMenuController>* 
SfxDispatcher_Impl::m_pActivePopupController = nullptr;
+
 /** This method checks if the stack of the SfxDispatchers is flushed, or if
     push- or pop- commands are pending.
 */
@@ -1685,7 +1690,52 @@ bool SfxDispatcher::FillState_(const SfxSlotServer& 
rSvr, SfxItemSet& rState,
     return false;
 }
 
-void SfxDispatcher::ExecutePopup( vcl::Window *pWin, const Point *pPos )
+namespace {
+
+static void 
lcl_FinishPopupDispatch(css::uno::Reference<css::frame::XPopupMenuController> 
xPopupController)
+{
+    css::uno::Reference<css::lang::XComponent> xComponent(xPopupController, 
css::uno::UNO_QUERY);
+    if (xComponent.is())
+        xComponent->dispose();
+    SfxDispatcher_Impl::m_pActivePopupController = nullptr;
+}
+
+struct SfxDispatcherPopupFinish final
+{
+    css::uno::Reference<css::frame::XPopupMenuController> m_xPopupController;
+    std::function<void(sal_Int16)> m_aCloseFunc;
+    rtl::Reference<::svt::DialogClosedListener> m_xDialogListener;
+    css::uno::Reference<css::awt::XPopupMenu> m_xPopupMenu;
+
+    DECL_LINK(PopupClosedHdl, css::ui::dialogs::DialogClosedEvent*, void);
+
+    
SfxDispatcherPopupFinish(css::uno::Reference<css::frame::XPopupMenuController> 
xPopupController,
+                             const std::function<void(sal_Int16)>& rCloseFunc,
+                             css::uno::Reference<css::awt::XPopupMenu> 
xPopupMenu)
+        : m_xPopupController(xPopupController)
+        , m_aCloseFunc(rCloseFunc)
+        , m_xDialogListener(new ::svt::DialogClosedListener())
+        , m_xPopupMenu(xPopupMenu)
+    {
+        m_xDialogListener->SetDialogClosedLink(LINK(this, 
SfxDispatcherPopupFinish, PopupClosedHdl));
+    }
+};
+
+IMPL_LINK(SfxDispatcherPopupFinish, PopupClosedHdl, 
css::ui::dialogs::DialogClosedEvent*, pEvt, void)
+{
+    assert(m_xPopupController.is());
+    if (!comphelper::LibreOfficeKit::isActive())
+        assert(SfxDispatcher_Impl::m_pActivePopupController == 
&m_xPopupController);
+    if (m_aCloseFunc)
+        m_aCloseFunc(pEvt ? pEvt->DialogResult : 0);
+    lcl_FinishPopupDispatch(m_xPopupController);
+    delete this;
+}
+
+} // anon namespace
+
+void SfxDispatcher::ExecutePopup(vcl::Window *pWin, const Point *pPos,
+    const std::function<void(sal_Int16)>& rCloseFunc)
 {
     SfxDispatcher &rDisp = *SfxGetpApp()->GetDispatcher_Impl();
     sal_uInt16 nShLevel = 0;
@@ -1699,7 +1749,7 @@ void SfxDispatcher::ExecutePopup( vcl::Window *pWin, 
const Point *pPos )
         const OUString& rResName = pSh->GetInterface()->GetPopupMenuName();
         if ( !rResName.isEmpty() )
         {
-            rDisp.ExecutePopup( rResName, pWin, pPos );
+            rDisp.ExecutePopup(rResName, pWin, pPos, rCloseFunc);
             return;
         }
     }
@@ -1808,7 +1858,8 @@ boost::property_tree::ptree 
SfxDispatcher::fillPopupMenu(const css::uno::Referen
     return ::fillPopupMenu(pVCLMenu);
 }
 
-void SfxDispatcher::ExecutePopup( const OUString& rResName, vcl::Window* pWin, 
const Point* pPos )
+void SfxDispatcher::ExecutePopup( const OUString& rResName, vcl::Window* pWin, 
const Point* pPos,
+    const std::function<void(sal_Int16)>& rCloseFunc)
 {
     css::uno::Sequence< css::uno::Any > aArgs{
         css::uno::Any(comphelper::makePropertyValue( "Value", rResName )),
@@ -1817,16 +1868,29 @@ void SfxDispatcher::ExecutePopup( const OUString& 
rResName, vcl::Window* pWin, c
     };
 
     css::uno::Reference< css::uno::XComponentContext > xContext = 
comphelper::getProcessComponentContext();
-    css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
-        xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
-        "com.sun.star.comp.framework.ResourceMenuController", aArgs, xContext 
), css::uno::UNO_QUERY );
+
+    if (!comphelper::LibreOfficeKit::isActive())
+        assert(!xImp->m_pActivePopupController);
+    if (!comphelper::LibreOfficeKit::isActive() && 
xImp->m_pActivePopupController)
+        return;
+
+    css::uno::Reference<css::frame::XPopupMenuController> xPopupController =
+        css::uno::Reference<css::frame::XPopupMenuController>(
+            
xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+            "com.sun.star.comp.framework.ResourceMenuController", aArgs, 
xContext), css::uno::UNO_QUERY);
+    if (!xPopupController.is())
+        return;
+    SfxDispatcher_Impl::m_pActivePopupController = &xPopupController;
 
     css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( 
xContext->getServiceManager()->createInstanceWithContext(
         "com.sun.star.awt.PopupMenu", xContext ), css::uno::UNO_QUERY );
-
-    if ( !xPopupController.is() || !xPopupMenu.is() )
+    if (!xPopupMenu.is())
+    {
+        lcl_FinishPopupDispatch(xPopupController);
         return;
+    }
 
+    struct SfxDispatcherPopupFinish* pFin = nullptr;
     vcl::Window* pWindow = pWin ? pWin : 
xImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
     Point aPos = pPos ? *pPos : pWindow->GetPointerPosPixel();
 
@@ -1852,14 +1916,22 @@ void SfxDispatcher::ExecutePopup( const OUString& 
rResName, vcl::Window* pWin, c
         OUString aMenuURL = "private:resource/popupmenu/" + rResName;
         if (GetFrame()->GetViewShell()->TryContextMenuInterception(xPopupMenu, 
aMenuURL, aEvent))
         {
+            const sal_Int16 nFlags = 
css::awt::PopupMenuDirection::EXECUTE_DOWN;
+            const css::awt::Rectangle aRect(aPos.X(), aPos.Y(), 1, 1);
             css::uno::Reference<css::awt::XWindowPeer> 
xParent(aEvent.SourceWindow, css::uno::UNO_QUERY);
-            xPopupMenu->execute(xParent, css::awt::Rectangle(aPos.X(), 
aPos.Y(), 1, 1), css::awt::PopupMenuDirection::EXECUTE_DOWN);
+            css::uno::Reference<css::awt::XPopupMenuAsync> 
xAsyncPopup(xPopupMenu, css::uno::UNO_QUERY);
+            pFin = new SfxDispatcherPopupFinish(xPopupController, rCloseFunc, 
xPopupMenu);
+            if (!rCloseFunc || !xAsyncPopup.is() || 
!xAsyncPopup->popup(xParent, aRect, nFlags, pFin->m_xDialogListener))
+            {
+                delete pFin;
+                pFin = nullptr;
+                xPopupMenu->execute(xParent, aRect, nFlags);
+            }
         }
     }
 
-    css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, 
css::uno::UNO_QUERY );
-    if ( xComponent.is() )
-        xComponent->dispose();
+    if (!pFin)
+        lcl_FinishPopupDispatch(xPopupController);
 }
 
 /** With this method the SfxDispatcher can be locked and released. A locked
diff --git a/sw/source/uibase/docvw/edtwin.cxx 
b/sw/source/uibase/docvw/edtwin.cxx
index eeb8554ccfcc..65c220f6eeb1 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -5457,7 +5457,7 @@ void SwEditWin::Command( const CommandEvent& rCEvt )
                         }
                     }
                     else if ( !m_rView.ExecSpellPopup( aDocPos ) )
-                        SfxDispatcher::ExecutePopup(this, &aPixPos);
+                        SfxDispatcher::ExecutePopup(this, &aPixPos, 
[](sal_Int16){});
                 }
                 else if (m_pApplyTempl->nUndo < 
rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount())
                 {
diff --git a/toolkit/inc/helper/unowrapper.hxx 
b/toolkit/inc/helper/unowrapper.hxx
index 03a9b525cc18..fdc65988bb62 100644
--- a/toolkit/inc/helper/unowrapper.hxx
+++ b/toolkit/inc/helper/unowrapper.hxx
@@ -56,7 +56,7 @@ public:
     virtual VclPtr<vcl::Window> GetWindow(const 
css::uno::Reference<css::awt::XWindow>& rxWindow) override;
 
     // Menu
-    virtual css::uno::Reference<css::awt::XPopupMenu> CreateMenuInterface( 
PopupMenu* pPopupMenu ) override;
+    virtual css::uno::Reference<css::awt::XPopupMenu> 
CreateMenuInterface(PopupMenu* pPopupMenu) override;
 
     void                WindowDestroyed( vcl::Window* pWindow ) override;
 
diff --git a/toolkit/source/awt/vclxmenu.cxx b/toolkit/source/awt/vclxmenu.cxx
index b17f32c2aebc..e2f78a2528ed 100644
--- a/toolkit/source/awt/vclxmenu.cxx
+++ b/toolkit/source/awt/vclxmenu.cxx
@@ -35,6 +35,7 @@
 #include <vcl/window.hxx>
 
 #include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
 
 VCLXMenu::VCLXMenu()
     : maMenuListeners( *this )
@@ -491,6 +492,33 @@ sal_Int16 VCLXMenu::execute(
                 static_cast<PopupMenuFlags>(nFlags) | 
PopupMenuFlags::NoMouseUpClose );
 }
 
+sal_Bool VCLXMenu::popup(
+    const css::uno::Reference< css::awt::XWindowPeer >& rxWindowPeer,
+    const css::awt::Rectangle& rPos, sal_Int16 nFlags,
+    const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& 
xListener)
+{
+    SolarMutexGuard aSolarGuard;
+    std::unique_lock aGuard( maMutex );
+
+    if (!mpMenu || !IsPopupMenu())
+        return false;
+
+    return 
static_cast<PopupMenu*>(mpMenu.get())->Popup(VCLUnoHelper::GetWindow(rxWindowPeer),
+                                   VCLRectangle(rPos), xListener.is() ? 
xListener : this,
+                                   static_cast<PopupMenuFlags>(nFlags) | 
PopupMenuFlags::NoMouseUpClose);
+}
+
+void SAL_CALL VCLXMenu::dialogClosed(const 
css::ui::dialogs::DialogClosedEvent&)
+{
+    SolarMutexGuard aSolarGuard;
+    std::unique_lock aGuard( maMutex );
+
+    assert(mpMenu && IsPopupMenu());
+    if (mpMenu && IsPopupMenu())
+        static_cast<PopupMenu*>(mpMenu.get())->Finish();
+}
+
+void SAL_CALL VCLXMenu::disposing(css::lang::EventObject const&) {}
 
 void SAL_CALL VCLXMenu::setCommand(
     sal_Int16 nItemId,
diff --git a/toolkit/source/helper/unowrapper.cxx 
b/toolkit/source/helper/unowrapper.cxx
index 6a12b915b4aa..ccd7e1213816 100644
--- a/toolkit/source/helper/unowrapper.cxx
+++ b/toolkit/source/helper/unowrapper.cxx
@@ -189,7 +189,7 @@ void UnoWrapper::SetWindowInterface( vcl::Window* pWindow, 
const css::uno::Refer
     }
 }
 
-css::uno::Reference<css::awt::XPopupMenu> UnoWrapper::CreateMenuInterface( 
PopupMenu* pPopupMenu )
+css::uno::Reference<css::awt::XPopupMenu> 
UnoWrapper::CreateMenuInterface(PopupMenu* pPopupMenu)
 {
     return new VCLXPopupMenu(pPopupMenu);
 }
diff --git a/vcl/inc/osx/salmenu.h b/vcl/inc/osx/salmenu.h
index 597180cc1ac3..dae1a1035cae 100644
--- a/vcl/inc/osx/salmenu.h
+++ b/vcl/inc/osx/salmenu.h
@@ -67,7 +67,9 @@ public:
     virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const 
Image& rImage) override;
     virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, 
const vcl::KeyCode& rKeyCode, const OUString& rKeyName ) override;
     virtual void GetSystemMenuData( SystemMenuData* pData ) override;
-    virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const 
tools::Rectangle& rRect, FloatWinPopupFlags nFlags) override;
+    virtual bool ShowNativePopupMenu(
+        FloatingWindow*, const tools::Rectangle&, FloatWinPopupFlags,
+        const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* = 
nullptr) override;
     virtual bool AddMenuBarButton( const SalMenuButtonItem& ) override;
     virtual void RemoveMenuBarButton( sal_uInt16 nId ) override;
     virtual tools::Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, 
SalFrame* i_pReferenceFrame ) override;
diff --git a/vcl/inc/qt5/QtMenu.hxx b/vcl/inc/qt5/QtMenu.hxx
index 11f3f00c5aa6..037f24ae62f5 100644
--- a/vcl/inc/qt5/QtMenu.hxx
+++ b/vcl/inc/qt5/QtMenu.hxx
@@ -38,7 +38,7 @@ class QtFrame;
 class QtMenu : public QObject, public SalMenu
 {
     Q_OBJECT
-private:
+
     std::vector<QtMenuItem*> maItems;
     VclPtr<Menu> mpVCLMenu;
     QtMenu* mpParentSalMenu;
@@ -50,6 +50,9 @@ private:
     // pointer to QMenu owned by the corresponding QtMenuItem or self (-> 
mpOwnedQMenu)
     QMenu* mpQMenu;
 
+    css::uno::Reference<css::ui::dialogs::XDialogClosedListener> m_xListener;
+    FloatingWindow* m_pWin;
+
     void DoFullMenuUpdate(Menu* pMenuBar);
     static void NativeItemText(OUString& rItemText);
 
@@ -71,8 +74,9 @@ public:
     virtual void SetFrame(const SalFrame* pFrame) override;
     const QtFrame* GetFrame() const;
     virtual void ShowMenuBar(bool bVisible) override;
-    virtual bool ShowNativePopupMenu(FloatingWindow* pWin, const 
tools::Rectangle& rRect,
-                                     FloatWinPopupFlags nFlags) override;
+    virtual bool ShowNativePopupMenu(
+        FloatingWindow*, const tools::Rectangle&, FloatWinPopupFlags,
+        const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* = 
nullptr) override;
     QtMenu* GetTopLevel();
     virtual void SetItemBits(unsigned nPos, MenuItemBits nBits) override;
     virtual void CheckItem(unsigned nPos, bool bCheck) override;
diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
index 79254d9f5fd5..6da1dae5f9e7 100644
--- a/vcl/inc/salmenu.hxx
+++ b/vcl/inc/salmenu.hxx
@@ -22,6 +22,7 @@
 
 #include <vcl/menu.hxx>
 #include <vcl/image.hxx>
+#include <com/sun/star/ui/dialogs/XDialogClosedListener.hpp>
 
 struct SystemMenuData;
 class FloatingWindow;
@@ -73,7 +74,17 @@ public:
     virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const 
Image& rImage ) = 0;
     virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, 
const vcl::KeyCode& rKeyCode, const OUString& rKeyName ) = 0;
     virtual void GetSystemMenuData( SystemMenuData* pData ) = 0;
-    virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const 
tools::Rectangle& rRect, FloatWinPopupFlags nFlags);
+    /**
+     * @param pListener
+     *     if !nullptr, the menu is supposed to be only shown and it'll run 
async.
+     *     Mainly means, when the menu is hidden, it must call the listener's
+     *     dialogClosed. The listener will destroy the SalMenu!
+     *
+     * @return
+     *     true, if the feature is implemented and was successful.
+     */
+    virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const 
tools::Rectangle& rRect, FloatWinPopupFlags nFlags,
+                                     const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* pListener = 
nullptr);
     virtual void ShowCloseButton(bool bShow);
     virtual bool AddMenuBarButton( const SalMenuButtonItem& ); // return false 
if not implemented or failure
     virtual void RemoveMenuBarButton( sal_uInt16 nId );
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index 85c0f5d3d893..5d5a487df8f1 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -132,7 +132,8 @@ public:
 #endif
     void ReturnFocus();
 
-    virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const 
tools::Rectangle& rRect, FloatWinPopupFlags nFlags) override;
+    virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const 
tools::Rectangle& rRect, FloatWinPopupFlags nFlags,
+                                     const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* = nullptr) 
override;
     virtual void ShowCloseButton(bool bShow) override;
     virtual bool AddMenuBarButton( const SalMenuButtonItem& rNewItem ) 
override;
     virtual void RemoveMenuBarButton( sal_uInt16 nId ) override;
diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx
index 3164ba873bae..0a91ab88cc36 100644
--- a/vcl/osx/salmenu.cxx
+++ b/vcl/osx/salmenu.cxx
@@ -281,8 +281,13 @@ AquaSalMenu::~AquaSalMenu()
     }
 }
 
-bool AquaSalMenu::ShowNativePopupMenu(FloatingWindow * pWin, const 
tools::Rectangle& rRect, FloatWinPopupFlags nFlags)
+bool AquaSalMenu::ShowNativePopupMenu(
+    FloatingWindow* pWin, const tools::Rectangle& rRect, FloatWinPopupFlags 
nFlags,
+    const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* 
pListener)
 {
+    if (pListener)
+        return false;
+
     // set offsets for positioning
     const float offset = 9.0;
 
diff --git a/vcl/qt5/QtMenu.cxx b/vcl/qt5/QtMenu.cxx
index fd38a0380000..61beac5d0968 100644
--- a/vcl/qt5/QtMenu.cxx
+++ b/vcl/qt5/QtMenu.cxx
@@ -92,6 +92,16 @@ void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, 
unsigned nPos)
             // no QMenu set, instantiate own one
             mpOwnedQMenu.reset(new QMenu);
             mpQMenu = mpOwnedQMenu.get();
+
+            connect(mpQMenu, &QMenu::aboutToHide, this, [this] {
+                if (m_pWin && m_xListener.is())
+                {
+                    QMenu* pMenu = mpOwnedQMenu.release();
+                    css::ui::dialogs::DialogClosedEvent 
aEvent(m_pWin->GetComponentInterface(), 0);
+                    m_xListener->dialogClosed(aEvent);
+                    pMenu->deleteLater();
+                }
+            });
         }
 
         if (pSalMenuItem->mpSubMenu)
@@ -676,15 +686,27 @@ void QtMenu::ShowCloseButton(bool bShow)
         pButton->hide();
 }
 
-bool QtMenu::ShowNativePopupMenu(FloatingWindow*, const tools::Rectangle&,
-                                 FloatWinPopupFlags nFlags)
+bool QtMenu::ShowNativePopupMenu(
+    FloatingWindow* pWin, const tools::Rectangle&, FloatWinPopupFlags nFlags,
+    const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* 
pListener)
 {
     assert(mpQMenu);
     DoFullMenuUpdate(mpVCLMenu);
     mpQMenu->setTearOffEnabled(bool(nFlags & 
FloatWinPopupFlags::AllowTearOff));
 
     const QPoint aPos = QCursor::pos();
-    mpQMenu->exec(aPos);
+    if (pListener)
+    {
+        m_xListener = *pListener;
+        m_pWin = pWin;
+        mpQMenu->popup(aPos);
+    }
+    else
+    {
+        m_xListener = nullptr;
+        m_pWin = nullptr;
+        mpQMenu->exec(aPos);
+    }
 
     return true;
 }
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index a8fdaf2a7978..b107bb0ca607 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -193,7 +193,9 @@ SalObject::~SalObject() {}
 
 SalMenu::~SalMenu() {}
 
-bool SalMenu::ShowNativePopupMenu(FloatingWindow*, const tools::Rectangle&, 
FloatWinPopupFlags)
+bool SalMenu::ShowNativePopupMenu(
+    FloatingWindow*, const tools::Rectangle&, FloatWinPopupFlags,
+    const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>*)
 {
     return false;
 }
diff --git a/vcl/source/control/managedmenubutton.cxx 
b/vcl/source/control/managedmenubutton.cxx
index 880730721ce2..f671cdd9c695 100644
--- a/vcl/source/control/managedmenubutton.cxx
+++ b/vcl/source/control/managedmenubutton.cxx
@@ -13,6 +13,7 @@
 #include <managedmenubutton.hxx>
 #include <vcl/menu.hxx>
 
+#include <com/sun/star/awt/XPopupMenuAsync.hpp>
 #include <com/sun/star/frame/ModuleManager.hpp>
 #include <com/sun/star/frame/theDesktop.hpp>
 #include <com/sun/star/frame/thePopupMenuControllerFactory.hpp>
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 46b899c14374..43f57eee0c6f 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -2660,6 +2660,7 @@ MenuFloatingWindow * PopupMenu::ImplGetFloatingWindow() 
const {
 }
 
 PopupMenu::PopupMenu()
+    : m_pState(nullptr)
 {
     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu(false, this);
 }
@@ -2672,6 +2673,7 @@ PopupMenu::PopupMenu( const PopupMenu& rMenu )
 
 PopupMenu::~PopupMenu()
 {
+    assert(!m_pState);
     disposeOnce();
 }
 
@@ -2769,6 +2771,36 @@ sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, 
const tools::Rectangle&
     return ImplExecute( pExecWindow, rRect, lcl_TranslateFlags(nFlags), 
nullptr, false );
 }
 
+struct PopupMenuFinishState final
+{
+    VclPtr<PopupMenu> pSelf;
+    VclPtr<vcl::Window> pParentWin;
+    VclPtr<MenuFloatingWindow> pWin;
+    bool bRealExecute;
+    bool bIsNativeMenu;
+
+    void clean()
+    {
+        pWin = nullptr;
+        pParentWin = nullptr;
+        pSelf = nullptr;
+    }
+};
+
+bool PopupMenu::Popup(vcl::Window* pExecWindow, const Point& rPopupPos,
+                            const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& listener)
+{
+    return Popup(pExecWindow, tools::Rectangle(rPopupPos, rPopupPos), 
listener, PopupMenuFlags::ExecuteDown);
+}
+
+bool PopupMenu::Popup(vcl::Window* pExecWindow, const tools::Rectangle& rRect,
+                      const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& listener, 
PopupMenuFlags nFlags)
+{
+    assert(!m_pState);
+    ENSURE_OR_RETURN(pExecWindow, "PopupMenu::Popup: need a non-NULL window!", 
false);
+    return ImplPopup(pExecWindow, rRect, lcl_TranslateFlags(nFlags), nullptr, 
false, listener);
+}
+
 void PopupMenu::ImplFlushPendingSelect()
 {
     // is there still Select?
@@ -2920,7 +2952,7 @@ bool PopupMenu::PrepareRun(const VclPtr<vcl::Window>& 
pParentWin, tools::Rectang
     if (pStartedFrom && pStartedFrom->IsMenuBar())
         nMaxHeight -= pParentWin->GetSizePixel().Height();
     sal_Int32 nLeft, nTop, nRight, nBottom;
-    pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
+    pWindow->GetBorder(nLeft, nTop, nRight, nBottom);
     nMaxHeight -= nTop+nBottom;
     if ( aSz.Height() > nMaxHeight )
     {
@@ -2936,10 +2968,11 @@ bool PopupMenu::PrepareRun(const VclPtr<vcl::Window>& 
pParentWin, tools::Rectang
 }
 
 bool PopupMenu::Run(const VclPtr<MenuFloatingWindow>& pWin, const bool 
bRealExecute, const bool bPreSelectFirst,
-                    const FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, 
const tools::Rectangle& rRect)
+                    const FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, 
const tools::Rectangle& rRect,
+                    const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* xListener)
 {
     SalMenu* pMenu = ImplGetSalMenu();
-    if (pMenu && bRealExecute && pMenu->ShowNativePopupMenu(pWin, rRect, 
nPopupModeFlags))
+    if (pMenu && bRealExecute && pMenu->ShowNativePopupMenu(pWin, rRect, 
nPopupModeFlags, xListener))
         return true;
 
     pWin->StartPopupMode(rRect, nPopupModeFlags);
@@ -2975,7 +3008,12 @@ bool PopupMenu::Run(const VclPtr<MenuFloatingWindow>& 
pWin, const bool bRealExec
     }
 
     if (bRealExecute)
-        pWin->Execute();
+    {
+        if (!xListener)
+            pWin->Execute();
+        else
+            pWin->Popup(*xListener);
+    }
 
     return false;
 }
@@ -3020,11 +3058,42 @@ sal_uInt16 PopupMenu::ImplExecute(const 
VclPtr<vcl::Window>& pParentWin, const t
     VclPtr<MenuFloatingWindow> pWin;
     if (!PrepareRun(pParentWin, aRect, nPopupModeFlags, pSFrom, bRealExecute, 
pWin))
         return 0;
-    const bool bNative = Run(pWin, bRealExecute, bPreSelectFirst, 
nPopupModeFlags, pSFrom, aRect);
+    const bool bNative = Run(pWin, bRealExecute, bPreSelectFirst, 
nPopupModeFlags, pSFrom, aRect, nullptr);
     FinishRun(pWin, pParentWin, bRealExecute, bNative);
     return nSelectedId;
 }
 
+bool PopupMenu::ImplPopup(const VclPtr<vcl::Window>& pParentWin, const 
tools::Rectangle& rRect,
+                          FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, 
bool bPreSelectFirst,
+                          const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener)
+{
+    // 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 false;
+    assert(!m_pState);
+    m_pState = new PopupMenuFinishState;
+    m_pState->bIsNativeMenu = Run(pWin, bRealExecute, bPreSelectFirst, 
nPopupModeFlags, pSFrom, aRect, &xListener);
+    m_pState->pWin = pWin;
+    m_pState->pParentWin = pParentWin;
+    m_pState->bRealExecute = bRealExecute;
+    m_pState->pSelf = xThis;
+    return true;
+}
+
+void PopupMenu::Finish()
+{
+    if (!m_pState)
+        return;
+    FinishRun(m_pState->pWin, m_pState->pParentWin, m_pState->bRealExecute, 
m_pState->bIsNativeMenu);
+    m_pState->clean();
+    delete m_pState;
+    m_pState = nullptr;
+}
+
 sal_uInt16 PopupMenu::ImplCalcVisEntries( tools::Long nMaxHeight, sal_uInt16 
nStartEntry, sal_uInt16* pLastVisible ) const
 {
     nMaxHeight -= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
diff --git a/vcl/source/window/menufloatingwindow.cxx 
b/vcl/source/window/menufloatingwindow.cxx
index cfd6a6ae190e..075fb97f5632 100644
--- a/vcl/source/window/menufloatingwindow.cxx
+++ b/vcl/source/window/menufloatingwindow.cxx
@@ -308,8 +308,15 @@ IMPL_LINK_NOARG(MenuFloatingWindow, PopupEnd, 
FloatingWindow*, void)
             pMenu->pStartedFrom->ClosePopup(pMenu);
     }
 
-    if ( pM )
+    if (pM)
+    {
         pM->pStartedFrom = nullptr;
+        if (m_xListener.is())
+        {
+            css::ui::dialogs::DialogClosedEvent 
aEvent(GetComponentInterface(), pM->GetCurItemId());
+            m_xListener->dialogClosed(aEvent);
+        }
+    }
 }
 
 IMPL_LINK_NOARG(MenuFloatingWindow, AutoScroll, Timer *, void)
@@ -443,21 +450,31 @@ void MenuFloatingWindow::End()
         Window::EndSaveFocus(xFocusId);
     }
 
+    Finish();
+
     bInExecute = false;
 }
 
-void MenuFloatingWindow::Execute()
+void MenuFloatingWindow::Popup(const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener)
 {
     ImplSVData* pSVData = ImplGetSVData();
-
     pSVData->maAppData.mpActivePopupMenu = 
static_cast<PopupMenu*>(pMenu.get());
-
+    m_xListener = xListener;
     Start();
+}
 
+void MenuFloatingWindow::Finish()
+{
+    ImplSVData* pSVData = ImplGetSVData();
+    pSVData->maAppData.mpActivePopupMenu = nullptr;
+}
+
+void MenuFloatingWindow::Execute()
+{
+    Popup();
     while (bInExecute && !Application::IsQuit())
         Application::Yield();
-
-    pSVData->maAppData.mpActivePopupMenu = nullptr;
+    Finish();
 }
 
 void MenuFloatingWindow::StopExecute()
@@ -474,6 +491,7 @@ void MenuFloatingWindow::StopExecute()
     // notify parent, needed for accessibility
     if( pMenu && pMenu->pStartedFrom )
         pMenu->pStartedFrom->ImplCallEventListeners( 
VclEventId::MenuSubmenuDeactivate, nPosInParent );
+    Finish();
 }
 
 void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
@@ -502,6 +520,7 @@ void MenuFloatingWindow::KillActivePopup( PopupMenu* 
pThisOnly )
 
         PaintImmediately();
     }
+    pPopup->Finish();
 }
 
 void MenuFloatingWindow::EndExecute()
diff --git a/vcl/source/window/menufloatingwindow.hxx 
b/vcl/source/window/menufloatingwindow.hxx
index f26fb50373ca..b6c8b54738ce 100644
--- a/vcl/source/window/menufloatingwindow.hxx
+++ b/vcl/source/window/menufloatingwindow.hxx
@@ -46,6 +46,7 @@ private:
     sal_uInt16 nScrollerHeight;
     sal_uInt16 nFirstEntry;
     sal_uInt16 nPosInParent;
+    css::uno::Reference<css::ui::dialogs::XDialogClosedListener> m_xListener;
 
     bool bInExecute : 1;
     bool bScrollMenu : 1;
@@ -67,6 +68,7 @@ private:
 
     void Start();
     void End();
+    static void Finish();
 
 protected:
     vcl::Region ImplCalcClipRegion() const;
@@ -107,6 +109,8 @@ public:
     bool IsScrollMenu() const        { return bScrollMenu; }
     sal_uInt16 GetScrollerHeight() const   { return nScrollerHeight; }
 
+    void Popup(const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener = 
nullptr);
+
     void Execute();
     void StopExecute();
     void EndExecute();
diff --git a/vcl/unx/gtk3/gtksalmenu.cxx b/vcl/unx/gtk3/gtksalmenu.cxx
index ac71e3390d87..0ccda0b66fb8 100644
--- a/vcl/unx/gtk3/gtksalmenu.cxx
+++ b/vcl/unx/gtk3/gtksalmenu.cxx
@@ -422,9 +422,13 @@ static void MenuClosed(GtkPopover* pWidget, GMainLoop* 
pLoop)
     g_main_loop_quit(pLoop);
 }
 
-bool GtkSalMenu::ShowNativePopupMenu(FloatingWindow* pWin, const 
tools::Rectangle& rRect,
-                                     FloatWinPopupFlags nFlags)
+bool GtkSalMenu::ShowNativePopupMenu
+    (FloatingWindow* pWin, const tools::Rectangle& rRect, FloatWinPopupFlags 
nFlags,
+     const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>* 
pListener)
 {
+    if (pListener)
+        return false;
+
     VclPtr<vcl::Window> xParent = pWin->ImplGetWindowImpl()->mpRealParent;
     mpFrame = static_cast<GtkSalFrame*>(xParent->ImplGetFrame());
 
commit 734616f041504506c49785462c0e9dc843a3517e
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 Apr 26 18:12:28 2022 +0200

    Refactor PopupMenu::ImplExecute for async support
    
    Splits ImplExecute into PrepareRun, Run and FinishRun.
    
    Change-Id: Ifddb1e968b468c9757eeece0bb19513cc26a9c8d

diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index 54df7ee66631..abad985775e4 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -493,7 +493,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 89bd5672088b..46b899c14374 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -2745,10 +2745,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;
@@ -2762,7 +2760,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()
@@ -2778,10 +2782,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();
 
@@ -2793,7 +2801,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;
@@ -2809,25 +2816,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 )
@@ -2857,10 +2863,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());
     }
@@ -2879,9 +2885,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();
@@ -2896,8 +2902,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();
@@ -2912,7 +2918,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;
@@ -2924,43 +2930,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
@@ -2971,22 +2968,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 )
@@ -2995,13 +3000,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
commit ce5146e5e72e1907c8cccfcfed876c7536deff99
Author:     Thorsten Behrens <thorsten.behr...@allotropia.de>
AuthorDate: Sat Nov 13 23:12:58 2021 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Apr 26 18:12:27 2022 +0200

    WASM default to notebookbar
    
    ..and use the full, desktop variant..
    
    Change-Id: Ib00aad8cd130b4a3433209c540fe82970c45c98e

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 462e2e5d25af..2086f531b6a8 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -6417,7 +6417,11 @@ static void activateNotebookbar(std::u16string_view rApp)
 
     if (aAppNode.isValid())
     {
+#ifdef EMSCRIPTEN
+        aAppNode.setNodeValue("Active", makeAny(OUString("notebookbar.ui")));
+#else
         aAppNode.setNodeValue("Active", 
makeAny(OUString("notebookbar_online.ui")));
+#endif
         aAppNode.commit();
     }
 }
@@ -6456,7 +6460,11 @@ static int lo_initialize(LibreOfficeKit* pThis, const 
char* pAppPath, const char
     static bool bPreInited = false;
     static bool bUnipoll = false;
     static bool bProfileZones = false;
+#ifdef EMSCRIPTEN
+    static bool bNotebookbar = true;
+#else
     static bool bNotebookbar = false;
+#endif
 
     { // cf. string lifetime for preinit
         std::vector<OUString> aOpts;
commit df52b6ec0fa8ed5c07686acc297bdab55027e3db
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Mon Dec 6 09:24:50 2021 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Apr 26 18:12:27 2022 +0200

    gbuild: build static unit tests
    
    While this generally works, the setup is not very practical. The
    unit tests become all very large, if they use components. The best
    static solution I can imagine is either just somehow linking them
    on demand, or create a single huge liblibreoffice.so, so keeping
    everthing almost static.
    
    Change-Id: If00f9ac3b3f63b915e3b5dcd931d233681a58006

diff --git a/Repository.mk b/Repository.mk
index 2152f22b251c..32ef179b6022 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -32,7 +32,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
        cfgex \
        concat-deps \
        cpp \
-       cppunittester \
+    $(call gb_CondCppunitMainLibOrExe,,cppunittester) \
        gbuildtojson \
        $(if $(filter MSC,$(COM)), \
                gcc-wrapper \
@@ -582,6 +582,7 @@ $(eval $(call gb_Helper_register_libraries,PLAINLIBS_NONE, \
        $(if $(filter MSC,$(COM)),cli_cppuhelper) \
        $(if $(filter $(OS),ANDROID),lo-bootstrap) \
        $(if $(filter $(OS),MACOSX),OOoSpotlightImporter) \
+    $(call gb_CondCppunitMainLibOrExe,cppunitmain) \
 ))
 
 $(eval $(call gb_Helper_register_libraries_for_install,PLAINLIBS_URE,ure, \
diff --git a/sal/Library_cppunitmain.mk b/sal/Library_cppunitmain.mk
new file mode 100644
index 000000000000..07f51e0c4821
--- /dev/null
+++ b/sal/Library_cppunitmain.mk
@@ -0,0 +1,42 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,cppunitmain))
+
+$(eval $(call gb_Library_set_include,cppunitmain,\
+    $$(INCLUDE) \
+    -I$(SRCDIR)/sal/inc \
+))
+
+$(eval $(call gb_Library_use_libraries,cppunitmain,\
+    sal \
+    unoexceptionprotector \
+    unobootstrapprotector \
+    vclbootstrapprotector \
+))
+
+$(eval $(call gb_Library_use_externals,cppunitmain,\
+    boost_headers \
+    cppunit \
+))
+
+$(eval $(call gb_Library_add_exception_objects,cppunitmain,\
+    sal/cppunittester/cppunittester \
+))
+
+ifeq ($(COM),MSC)
+
+$(eval $(call gb_Library_add_ldflags,cppunitmain,\
+    /STACK:10000000 \
+))
+
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/sal/Module_sal.mk b/sal/Module_sal.mk
index e0448a5085bf..6c18d6282977 100644
--- a/sal/Module_sal.mk
+++ b/sal/Module_sal.mk
@@ -10,7 +10,7 @@
 $(eval $(call gb_Module_Module,sal))
 
 $(eval $(call gb_Module_add_targets,sal,\
-       $(if $(CROSS_COMPILING),,$(if $(filter 
TRUE,$(DISABLE_DYNLOADING)),,Executable_cppunittester)) \
+    $(call 
gb_CondCppunitMainLibOrExe,Library_cppunitmain,Executable_cppunittester) \
        $(if $(filter $(OS),ANDROID), \
                Library_lo-bootstrap) \
        Library_sal \
diff --git a/sal/cppunittester/cppunittester.cxx 
b/sal/cppunittester/cppunittester.cxx
index fec62c261260..18773b2a67b6 100644
--- a/sal/cppunittester/cppunittester.cxx
+++ b/sal/cppunittester/cppunittester.cxx
@@ -230,13 +230,17 @@ class CPPUNIT_API ProtectedFixtureFunctor
 {
 private:
     const std::string &testlib;
+#ifndef DISABLE_DYNLOADING
     const std::string &args;
+#endif
     std::vector<CppUnit::Protector *> &protectors;
     CppUnit::TestResult &result;
 public:
     ProtectedFixtureFunctor(const std::string& testlib_, const std::string 
&args_, std::vector<CppUnit::Protector*> &protectors_, CppUnit::TestResult 
&result_)
         : testlib(testlib_)
+#ifndef DISABLE_DYNLOADING
         , args(args_)
+#endif
         , protectors(protectors_)
         , result(result_)
     {
diff --git a/solenv/gbuild/Conditions.mk b/solenv/gbuild/Conditions.mk
index 0a7b88969557..4cb5688997e9 100644
--- a/solenv/gbuild/Conditions.mk
+++ b/solenv/gbuild/Conditions.mk
@@ -12,6 +12,10 @@
 # just end in two (!) braces, otherwise you may need to use either the $(1)
 # or the $(2) multiple times.
 
+define gb_CondCppunitMainLibOrExe
+$(if $(or $(CROSS_COMPILING),$(DISABLE_DYNLOADING)),$(1),$(2))
+endef
+
 define gb_CondExeLockfile
 $(if $(and $(filter-out ANDROID MACOSX iOS WNT,$(OS))),$(1),$(2))
 endef
diff --git a/solenv/gbuild/CppunitTest.mk b/solenv/gbuild/CppunitTest.mk
index 995910cfbd0c..8e9392e5c397 100644
--- a/solenv/gbuild/CppunitTest.mk
+++ b/solenv/gbuild/CppunitTest.mk
@@ -21,6 +21,7 @@
 
 gb_CppunitTest_UNITTESTFAILED ?= 
$(GBUILDDIR)/platform/unittest-failed-default.sh
 gb_CppunitTest_PYTHONDEPS ?= $(call gb_Library_get_target,pyuno_wrapper) $(if 
$(SYSTEM_PYTHON),,$(call gb_Package_get_target,python3))
+gb_CppunitTest_KNOWN :=
 
 ifneq ($(strip $(CPPUNITTRACE)),)
 ifneq ($(filter gdb,$(CPPUNITTRACE)),)
@@ -70,8 +71,13 @@ endif
 
 # defined by platform
 #  gb_CppunitTest_get_filename
+ifeq (,$(DISABLE_DYNLOADING))
 gb_CppunitTest_RUNTIMEDEPS := $(call 
gb_Executable_get_runtime_dependencies,cppunittester)
 gb_CppunitTest_CPPTESTCOMMAND := $(call 
gb_Executable_get_target_for_build,cppunittester)
+else
+gb_CppunitTest_RUNTIMEDEPS :=
+gb_CppunitTest_CPPTESTCOMMAND :=
+endif
 
 # i18npool dlopens localedata_* libraries.
 gb_CppunitTest_RUNTIMEDEPS += \
@@ -198,6 +204,11 @@ $(call gb_CppunitTest_get_target,$(1)) : HEADLESS := 
--headless
 $(call gb_CppunitTest_get_target,$(1)) : EXTRA_ENV_VARS :=
 $$(eval $$(call gb_Module_register_target,$(call 
gb_CppunitTest_get_target,$(1)),$(call gb_CppunitTest_get_clean_target,$(1))))
 $(call gb_Helper_make_userfriendly_targets,$(1),CppunitTest)
+ifeq ($(DISABLE_DYNLOADING),TRUE)
+$$(eval $$(call gb_CppunitTest_use_libraries,$(1),cppunitmain))
+$$(eval $$(call gb_CppunitTest_add_defs,$(1),-D__EMSCRIPTEN__))
+endif
+$(if $(filter $(1),$(gb_CppunitTest_KNOWN)),,gb_CppunitTest_KNOWN += $(1))
 
 endef
 
diff --git a/solenv/gbuild/TargetLocations.mk b/solenv/gbuild/TargetLocations.mk
index 32d7eed72ec0..253e01acf5fd 100644
--- a/solenv/gbuild/TargetLocations.mk
+++ b/solenv/gbuild/TargetLocations.mk
@@ -53,6 +53,7 @@ gb_CompilerTest_get_target = $(WORKDIR)/CompilerTest/$(1)
 gb_ComponentTarget_get_target = $(WORKDIR)/ComponentTarget/$(1).component
 gb_ComponentTarget_get_target_for_build = 
$(WORKDIR_FOR_BUILD)/ComponentTarget/$(1).component
 gb_Configuration_get_preparation_target = 
$(WORKDIR)/Configuration/$(1).prepared
+gb_CppunitTest_get_linktargetfile = $(call gb_LinkTarget_get_target,$(call 
gb_CppunitTest_get_linktarget,$1))
 gb_CppunitTest_get_target = $(WORKDIR)/CppunitTest/$(1).test
 gb_CustomPackage_get_target = $(WORKDIR)/CustomPackage/$(1).filelist
 gb_CustomTarget_get_repo_target = $(WORKDIR)/CustomTarget/$(2)_$(1).done
diff --git a/solenv/gbuild/extensions/post_SpeedUpTargets.mk 
b/solenv/gbuild/extensions/post_SpeedUpTargets.mk
index 3db6355ab90d..6fcbe243a01f 100644
--- a/solenv/gbuild/extensions/post_SpeedUpTargets.mk
+++ b/solenv/gbuild/extensions/post_SpeedUpTargets.mk
@@ -52,7 +52,6 @@ endif
 
 endif
 
-
 ifneq (,$(filter build,$(gb_Module_SKIPTARGETS)))
 gb_Module_add_target =
 endif
diff --git a/solenv/gbuild/gbuild.mk b/solenv/gbuild/gbuild.mk
index 075c029b095d..c07ade7b4b18 100644
--- a/solenv/gbuild/gbuild.mk
+++ b/solenv/gbuild/gbuild.mk
@@ -292,6 +292,7 @@ gb_TEST_ENV_VARS += 
SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION=1
 ifeq (,$(SAL_USE_VCLPLUGIN))
 gb_TEST_ENV_VARS += SAL_USE_VCLPLUGIN=svp
 endif
+gb_TEST_ENV_VARS += STATIC_UNO_HOME=file://$$I/program
 
 # This is used to detect whether LibreOffice is being built (as opposed to 
building
 # 3rd-party code). Used for tag deprecation for API we want to
diff --git a/solenv/gbuild/platform/unxgcc.mk b/solenv/gbuild/platform/unxgcc.mk
index b98732030b32..037f462d2795 100644
--- a/solenv/gbuild/platform/unxgcc.mk
+++ b/solenv/gbuild/platform/unxgcc.mk
@@ -312,12 +312,18 @@ endef
 
 gb_CppunitTest_CPPTESTPRECOMMAND := \
     $(call 
gb_Helper_extend_ld_path,$(WORKDIR)/UnpackedTarball/cppunit/src/cppunit/.libs)
-gb_CppunitTest_get_filename = libtest_$(1).so
+ifeq (,$(DISABLE_DYNLOADING))
+gb_CppunitTest_get_filename = libtest_$(1)$(gb_Library_PLAINEXT)
+else
+gb_CppunitTest_get_filename = test_$(1)$(gb_Executable_EXT)
+endif
 gb_CppunitTest_get_ilibfilename = $(gb_CppunitTest_get_filename)
 gb_CppunitTest_malloc_check := -ex 'set environment MALLOC_CHECK_=2; set 
environment MALLOC_PERTURB_=153'
 
 define gb_CppunitTest_CppunitTest_platform
+ifeq (,$(DISABLE_DYNLOADING))
 $(call gb_LinkTarget_get_target,$(2)) : RPATH := $(call 
gb_Library__get_rpath,$(call gb_LinkTarget__get_rpath_for_layer,NONE))
+endif
 
 endef
 
diff --git a/solenv/gbuild/static.mk b/solenv/gbuild/static.mk
index faa9a73db516..1b7f0214900a 100644
--- a/solenv/gbuild/static.mk
+++ b/solenv/gbuild/static.mk
@@ -198,6 +198,8 @@ $(foreach lib,$(gb_Library_KNOWNLIBS), \
     $(eval $(call gb_LinkTarget__fill_all_deps,$(call 
gb_Library_get_linktarget,$(lib)))))
 $(foreach exec,$(gb_Executable_KNOWN), \
     $(eval $(call gb_LinkTarget__expand_executable,$(call 
gb_Executable_get_linktarget,$(exec)))))
+$(foreach cppunit,$(gb_CppunitTest_KNOWN), \
+    $(eval $(call gb_LinkTarget__expand_executable,$(call 
gb_CppunitTest_get_linktarget,$(cppunit)))))
 $(foreach workdir_linktargetname,$(gb_LinkTarget__ALL_TOUCHED), \
     $(eval $(call gb_LinkTarget__remove_touch,$(workdir_linktargetname))))
 
@@ -235,11 +237,14 @@ endef
 endef # gb_LinkTarget__expand_executable_template
 
 ifneq (,$(gb_DEBUG_STATIC))
+$(info $(call gb_LinkTarget__expand_executable_template,CppunitTest))
 $(info $(call gb_LinkTarget__expand_executable_template,Executable))
 endif
+$(eval $(call gb_LinkTarget__expand_executable_template,CppunitTest))
 $(eval $(call gb_LinkTarget__expand_executable_template,Executable))
 
 $(foreach exec,$(gb_Executable_KNOWN),$(eval $(call 
gb_Executable__expand_deps,$(exec))))
+$(foreach cppunit,$(gb_CppunitTest_KNOWN),$(eval $(call 
gb_CppunitTest__expand_deps,$(cppunit))))
 
 endif # gb_PARTIAL_BUILD
 endif # gb_FULLDEPS
commit 8628b20bc8e3a160240096fdc954cd80e58ba555
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Sat Jan 8 22:53:29 2022 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Apr 26 18:12:27 2022 +0200

    gbuild: set unorc lookup dir via environment
    
    UNO tries hard to find the path of the executable to look at that
    place for its unorc / uno.ini. All these approaches don't work for
    static binaries, so just override the lookup with the environment
    variable STATIC_UNO_HOME.
    
    Change-Id: I0d80c91e474d9f869475ba752d708b77c99f8a56

diff --git a/Makefile.in b/Makefile.in
index 9c0f2aefb9da..30dd79a65787 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -7,6 +7,8 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 
+unexport STATIC_UNO_HOME
+
 gb_Top_MODULE_CHECK_TARGETS := slowcheck unitcheck subsequentcheck perfcheck 
uicheck screenshot
 
 .PHONY : check-if-root bootstrap gbuild build build-non-l10n-only 
build-l10n-only check clean clean-build clean-host test-install distclean 
distro-pack-install docs download etags fetch get-submodules id install 
install-gdb-printers install-strip tags debugrun help showmodules translations 
packageinfo internal.clean $(gb_Top_MODULE_CHECK_TARGETS)
diff --git a/bin/run b/bin/run
index 523da3c0e178..f812c2baadbb 100755
--- a/bin/run
+++ b/bin/run
@@ -67,6 +67,8 @@ else
 
 fi
 
+test "${STATIC_UNO_HOME+set}" = set || export 
STATIC_UNO_HOME="file://${dir}/instdir/program"
+
 # echo "setting URE_BOOTSTRAP to: ${URE_BOOTSTRAP}"
 # echo "setting search path to: ${SEARCH_PATH}"
 # echo "execing: ${exedir}/$1"
diff --git a/cppuhelper/source/paths.cxx b/cppuhelper/source/paths.cxx
index ece7650ded4c..0c0a3fbd5580 100644
--- a/cppuhelper/source/paths.cxx
+++ b/cppuhelper/source/paths.cxx
@@ -20,12 +20,14 @@
 #include <config_folders.h>
 
 #include <sal/config.h>
+#include <sal/log.hxx>
 
 #include <cassert>
 
 #include <com/sun/star/uno/DeploymentException.hpp>
 #include <osl/file.hxx>
 #include <osl/module.hxx>
+#include <osl/thread.h>
 #include <rtl/ustring.hxx>
 #include <sal/types.h>
 #include <o3tl/string_view.hxx>
@@ -65,7 +67,16 @@ OUString cppu::getUnoIniUri() {
 #elif defined(EMSCRIPTEN)
     OUString uri("file:///instdir/program");
 #else
-    OUString uri(get_this_libpath());
+
+    OUString uri;
+#ifdef DISABLE_DYNLOADING
+    static const char* uno_home = getenv("STATIC_UNO_HOME");
+    if (uno_home)
+        uri = OStringToOUString(uno_home, osl_getThreadTextEncoding());
+    else
+#endif
+        uri = get_this_libpath();
+
 #ifdef MACOSX
     // We keep the URE dylibs directly in "Frameworks" (that is, 
LIBO_LIB_FOLDER) and unorc in
     // "Resources/ure/etc" (LIBO_URE_ETC_FOLDER).
@@ -75,7 +86,9 @@ OUString cppu::getUnoIniUri() {
     }
 #endif
 #endif
-    return uri + "/" SAL_CONFIGFILE("uno");
+    uri += "/" SAL_CONFIGFILE("uno");
+    SAL_INFO("cppuhelper", "expected uno config: " << uri);
+    return uri;
 }
 
 bool cppu::nextDirectoryItem(osl::Directory & directory, OUString * url) {
diff --git a/desktop/scripts/soffice.sh b/desktop/scripts/soffice.sh
index 67cc0b89751f..1bfb60682648 100755
--- a/desktop/scripts/soffice.sh
+++ b/desktop/scripts/soffice.sh
@@ -176,6 +176,8 @@ else
     unset LC_ALL
 fi
 
+test "${STATIC_UNO_HOME+set}" = set || export 
STATIC_UNO_HOME="file://${sd_prog}"
+
 # run soffice.bin directly when you want to get the backtrace
 if [ -n "$GDBTRACECHECK" ] ; then
     exec $GDBTRACECHECK "$sd_prog/soffice.bin" "$@"
commit 98ae340307786c8fe18addc3714c9b859fdf12dd
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Apr 22 19:26:47 2022 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Apr 25 11:13:10 2022 +0200

    tdf#135978 sw_redlinehide: recreate fly frames anchored to subsequent nodes
    
    ... in SwTextNode::JoinNext().
    
    The 2nd node is deleted, so its frame is deleted, and if it is the start
    of a merged frame, fly frames on the node itself will be recreated
    already, but those on subseqent nodes need an extra call.
    
    Change-Id: I18999946334f5560b720d3d275610bc8b07973f6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133335
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx 
b/sw/qa/extras/uiwriter/uiwriter.cxx
index 8934ee1617ea..104d9a6b213b 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -374,6 +374,57 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf67238)
     
CPPUNIT_ASSERT(!((rTable.GetTableBox("C3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf135978)
+{
+    SwDoc* pDoc = createSwDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+    pWrtShell->Insert("foobar");
+    pWrtShell->SplitNode();
+    pWrtShell->Insert("bazquux");
+
+    CPPUNIT_ASSERT(pWrtShell->IsEndOfDoc());
+
+    SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR);
+    anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint());
+    SfxItemSet flySet(pDoc->GetAttrPool(), svl::Items<RES_ANCHOR, RES_ANCHOR>);
+    flySet.Put(anchor);
+    SwFlyFrameFormat const* pFly = dynamic_cast<SwFlyFrameFormat const*>(
+            pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true));
+    CPPUNIT_ASSERT(pFly != nullptr);
+    CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+    // move cursor back to body
+    pWrtShell->SttEndDoc(/*bStt=*/false);
+
+    // hide and enable
+    dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
+    dispatchCommand(mxComponent, ".uno:TrackChanges", {});
+
+    CPPUNIT_ASSERT(pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+    CPPUNIT_ASSERT(
+        
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+    CPPUNIT_ASSERT(pWrtShell->GetLayout()->IsHideRedlines());
+
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 6, 
/*bBasicCall=*/false);
+    pWrtShell->Delete();
+
+    // now split
+    pWrtShell->SttEndDoc(/*bStt=*/true);
+    pWrtShell->SplitNode();
+    CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+
+    // the problem was that undo removed the fly frame from the layout
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+
+    pWrtShell->Redo();
+    CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo75110)
 {
     SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "fdo75110.odt");
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 088792546980..68223f742796 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -883,6 +883,11 @@ void CheckResetRedlineMergeFlag(SwTextNode & rNode, 
Recreate const eRecreateMerg
             {
                 
assert(pFrame->GetMergedPara()->listener.IsListeningTo(&rNode));
                 assert(rNode.GetIndex() <= 
pFrame->GetMergedPara()->pLastNode->GetIndex());
+                // tdf#135978 Join: recreate fly frames anchored to subsequent 
nodes
+                if (eRecreateMerged == sw::Recreate::ThisNode)
+                {
+                    AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, rNode, 
nullptr);
+                }
             }
             eMode = sw::FrameMode::New; // Existing is not idempotent!
         }
commit 870ee667daa08bea0a60de40b13135da73e71e4c
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Sun Apr 24 21:22:47 2022 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Mon Apr 25 09:58:45 2022 +0200

    ofz#46905 Null-dereference
    
    Change-Id: I26427ee1e010ce79e40c550459d9f53598570a7b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133360
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx
index 4ea677b0bbfe..b652ce34408c 100644
--- a/vcl/source/outdev/textline.cxx
+++ b/vcl/source/outdev/textline.cxx
@@ -680,6 +680,8 @@ void OutputDevice::ImplDrawStrikeoutChar( tools::Long 
nBaseX, tools::Long nBaseY
     int nStrikeStrLen = (nWidth+(nStrikeoutWidth-1)) / nStrikeoutWidth;
     if( nStrikeStrLen > nMaxStrikeStrLen )
         nStrikeStrLen = nMaxStrikeStrLen;
+    else if (nStrikeStrLen < 0)
+        nStrikeStrLen = 0;
 
     // build the strikeout string
     for( int i = nTestStrLen; i < nStrikeStrLen; ++i)
commit fe672dc74231c275a0b5593448f26d26b658743b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Apr 25 08:19:12 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Apr 25 09:10:42 2022 +0200

    sw: prefix members of WW8_WrPct, WW8_WrPlc1, WW8_WrPlcField and ...
    
    ... WW8_WrPlcFootnoteEdn
    
    See tdf#94879 for motivation.
    
    Change-Id: Ie49a167ca443216322a2038d4d6568d43736019a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133361
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index 44196f0207d9..7cc40d97713c 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -793,9 +793,9 @@ const SfxPoolItem& MSWordExportBase::GetItem(sal_uInt16 
nWhich) const
 }
 
 WW8_WrPlc1::WW8_WrPlc1( sal_uInt16 nStructSz )
-    : pData( new sal_uInt8[ 16 * nStructSz ] ),
-      nDataLen(16 * nStructSz),
-      nStructSiz( nStructSz )
+    : m_pData( new sal_uInt8[ 16 * nStructSz ] ),
+      m_nDataLen(16 * nStructSz),
+      m_nStructSiz( nStructSz )
 {
 }
 
@@ -805,43 +805,43 @@ WW8_WrPlc1::~WW8_WrPlc1()
 
 WW8_CP WW8_WrPlc1::Prev() const
 {
-    bool b = !aPos.empty();
+    bool b = !m_aPos.empty();
     OSL_ENSURE(b,"Prev called on empty list");
-    return b ? aPos.back() : 0;
+    return b ? m_aPos.back() : 0;
 }
 
 void WW8_WrPlc1::Append( WW8_CP nCp, const void* pNewData )
 {
-    sal_uLong nInsPos = aPos.size() * nStructSiz;
-    aPos.push_back( nCp );
-    if( nDataLen < nInsPos + nStructSiz )
+    sal_uLong nInsPos = m_aPos.size() * m_nStructSiz;
+    m_aPos.push_back( nCp );
+    if( m_nDataLen < nInsPos + m_nStructSiz )
     {
-        sal_uInt8* pNew = new sal_uInt8[ 2 * nDataLen ];
-        memcpy( pNew, pData.get(), nDataLen );
-        pData.reset(pNew);
-        nDataLen *= 2;
+        sal_uInt8* pNew = new sal_uInt8[ 2 * m_nDataLen ];
+        memcpy( pNew, m_pData.get(), m_nDataLen );
+        m_pData.reset(pNew);
+        m_nDataLen *= 2;
     }
-    memcpy( pData.get() + nInsPos, pNewData, nStructSiz );
+    memcpy( m_pData.get() + nInsPos, pNewData, m_nStructSiz );
 }
 
 void WW8_WrPlc1::Finish( sal_uLong nLastCp, sal_uLong nSttCp )
 {
-    if( !aPos.empty() )
+    if( !m_aPos.empty() )
     {
-        aPos.push_back( nLastCp );
+        m_aPos.push_back( nLastCp );
         if( nSttCp )
-            for(WW8_CP & rCp : aPos)
+            for(WW8_CP & rCp : m_aPos)
                 rCp -= nSttCp;
     }
 }
 
 void WW8_WrPlc1::Write( SvStream& rStrm )
 {
-    decltype(aPos)::size_type i;
-    for( i = 0; i < aPos.size(); ++i )
-        SwWW8Writer::WriteLong( rStrm, aPos[i] );
+    decltype(m_aPos)::size_type i;
+    for( i = 0; i < m_aPos.size(); ++i )
+        SwWW8Writer::WriteLong( rStrm, m_aPos[i] );
     if( i )
-        rStrm.WriteBytes(pData.get(), (i-1) * nStructSiz);
+        rStrm.WriteBytes(m_pData.get(), (i-1) * m_nStructSiz);
 }
 
 // Class WW8_WrPlcField for fields
@@ -853,7 +853,7 @@ void WW8_WrPlcField::Write( WW8Export& rWrt )
 
     WW8_FC *pfc;
     sal_Int32 *plc;
-    switch (nTextTyp)
+    switch (m_nTextTyp)
     {
         case TXT_MAINTEXT:
             pfc = &rWrt.m_pFib->m_fcPlcffldMom;
@@ -1328,9 +1328,9 @@ WW8_FC WW8_WrFkp::GetEndFc() const
 
 // Method for managing the piece table
 WW8_WrPct::WW8_WrPct(WW8_FC nfcMin)
-    : nOldFc(nfcMin)
+    : m_nOldFc(nfcMin)
 {
-    AppendPc(nOldFc);
+    AppendPc(m_nOldFc);
 }
 
 WW8_WrPct::~WW8_WrPct()
@@ -1340,14 +1340,14 @@ WW8_WrPct::~WW8_WrPct()
 // Fill the piece and create a new one
 void WW8_WrPct::AppendPc(WW8_FC nStartFc)
 {
-    WW8_CP nStartCp = nStartFc - nOldFc;    // subtract the beginning of the 
text
+    WW8_CP nStartCp = nStartFc - m_nOldFc;    // subtract the beginning of the 
text
     if ( !nStartCp && !m_Pcts.empty())
     {
         OSL_ENSURE(1 == m_Pcts.size(), "empty Piece!");
         m_Pcts.pop_back();
     }
 
-    nOldFc = nStartFc;                      // remember StartFc as old
+    m_nOldFc = nStartFc;                      // remember StartFc as old
 
     nStartCp >>= 1;     // for Unicode: number of characters / 2
 
@@ -1375,7 +1375,7 @@ void WW8_WrPct::WritePc( WW8Export& rWrt )
     }
 
     // calculate the last Pos
-    sal_uLong nStartCp = rWrt.m_pFib->m_fcMac - nOldFc;
+    sal_uLong nStartCp = rWrt.m_pFib->m_fcMac - m_nOldFc;
     nStartCp >>= 1;             // For Unicode: number of characters / 2
     nStartCp += m_Pcts.back()->GetStartCp();
     SwWW8Writer::WriteLong( *rWrt.m_pTableStrm, nStartCp );
@@ -1407,10 +1407,10 @@ void WW8_WrPct::SetParaBreak()
 
 WW8_CP WW8_WrPct::Fc2Cp( sal_uLong nFc ) const
 {
-    OSL_ENSURE( nFc >= o3tl::make_unsigned(nOldFc), "FilePos lies in front of 
last piece" );
+    OSL_ENSURE( nFc >= o3tl::make_unsigned(m_nOldFc), "FilePos lies in front 
of last piece" );
     OSL_ENSURE( ! m_Pcts.empty(), "Fc2Cp no piece available" );
 
-    nFc -= nOldFc;
+    nFc -= m_nOldFc;
     nFc /= 2; // Unicode
     return nFc + m_Pcts.back()->GetStartCp();
 }
@@ -3974,7 +3974,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT sal_uInt32 
GetSaveWarningOfMSVBAStorage_ww8(  Sf
 bool WW8_WrPlcFootnoteEdn::WriteText( WW8Export& rWrt )
 {
     bool bRet = false;
-    if (TXT_FTN == nTyp)
+    if (TXT_FTN == m_nTyp)
     {
         bRet = WriteGenericText( rWrt, TXT_FTN, rWrt.m_pFib->m_ccpFootnote );
         rWrt.m_pFieldFootnote->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
@@ -3992,7 +3992,7 @@ bool WW8_WrPlcFootnoteEdn::WriteText( WW8Export& rWrt )
 
 void WW8_WrPlcFootnoteEdn::WritePlc( WW8Export& rWrt ) const
 {
-    if( TXT_FTN == nTyp )
+    if( TXT_FTN == m_nTyp )
     {
         WriteGenericPlc( rWrt, TXT_FTN, rWrt.m_pFib->m_fcPlcffndText,
             rWrt.m_pFib->m_lcbPlcffndText, rWrt.m_pFib->m_fcPlcffndRef,
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 7e3046214fdd..b798b99a6b75 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -282,7 +282,7 @@ public:
 class WW8_WrPct
 {
     std::vector<std::unique_ptr<WW8_WrPc>> m_Pcts;
-    WW8_FC nOldFc;
+    WW8_FC m_nOldFc;
 public:
     explicit WW8_WrPct(WW8_FC nStartFc);
     ~WW8_WrPct();
@@ -1239,12 +1239,12 @@ protected:
 class WW8_WrPlcFootnoteEdn : public WW8_WrPlcSubDoc
 {
 private:
-    sal_uInt8 nTyp;
+    sal_uInt8 m_nTyp;
 
     WW8_WrPlcFootnoteEdn(const WW8_WrPlcFootnoteEdn&) = delete;
     WW8_WrPlcFootnoteEdn& operator=(WW8_WrPlcFootnoteEdn const &) = delete;
 public:
-    explicit WW8_WrPlcFootnoteEdn( sal_uInt8 nTTyp ) : nTyp( nTTyp ) {}
+    explicit WW8_WrPlcFootnoteEdn( sal_uInt8 nTTyp ) : m_nTyp( nTTyp ) {}
 
     bool WriteText( WW8Export& rWrt );
     void WritePlc( WW8Export& rWrt ) const;
@@ -1336,15 +1336,15 @@ public:
 class WW8_WrPlc1
 {
 private:
-    std::vector<WW8_CP> aPos;
-    std::unique_ptr<sal_uInt8[]> pData;                // content ( structures 
)
-    sal_uLong nDataLen;
-    sal_uInt16 nStructSiz;
+    std::vector<WW8_CP> m_aPos;
+    std::unique_ptr<sal_uInt8[]> m_pData;                // content ( 
structures )
+    sal_uLong m_nDataLen;
+    sal_uInt16 m_nStructSiz;
 
     WW8_WrPlc1(const WW8_WrPlc1&) = delete;
     WW8_WrPlc1& operator=(const WW8_WrPlc1&) = delete;
 protected:
-    sal_uInt16 Count() const { return aPos.size(); }
+    sal_uInt16 Count() const { return m_aPos.size(); }
     void Write( SvStream& rStrm );
     WW8_CP Prev() const;
 public:
@@ -1358,18 +1358,18 @@ public:
 class WW8_WrPlcField : public WW8_WrPlc1
 {
 private:
-    sal_uInt8 nTextTyp;
-    sal_uInt16 nResults;
+    sal_uInt8 m_nTextTyp;
+    sal_uInt16 m_nResults;
 
     WW8_WrPlcField(const WW8_WrPlcField&) = delete;
     WW8_WrPlcField& operator=(const WW8_WrPlcField&) = delete;
 public:
     WW8_WrPlcField( sal_uInt16 nStructSz, sal_uInt8 nTTyp )
-        : WW8_WrPlc1( nStructSz ), nTextTyp( nTTyp ), nResults(0)
+        : WW8_WrPlc1( nStructSz ), m_nTextTyp( nTTyp ), m_nResults(0)
     {}
     void Write( WW8Export& rWrt );
-    void ResultAdded() { ++nResults; }
-    sal_uInt16 ResultCount() const { return nResults; }
+    void ResultAdded() { ++m_nResults; }
+    sal_uInt16 ResultCount() const { return m_nResults; }
 };
 
 class WW8_WrMagicTable : public WW8_WrPlc1
commit 655e5d4406e15774a76c945a57700d21516813c1
Author:     Gabor Kelemen <kelem...@ubuntu.com>
AuthorDate: Mon Apr 18 14:54:26 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Apr 25 08:43:38 2022 +0200

    find-unneeded-includes: bail out early if no files are found with 
--recursive
    
    Change-Id: I5bd726b33e4fc7068baad91ff185763274307b35
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133308
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/bin/find-unneeded-includes b/bin/find-unneeded-includes
index f58677c48bb7..cc694fcb41a6 100755
--- a/bin/find-unneeded-includes
+++ b/bin/find-unneeded-includes
@@ -346,6 +346,13 @@ def main(argv):
 
     # quickly sanity check whether files with exceptions in yaml still exists
     # only check for the module of the very first filename passed
+
+    # Verify there are files selected for checking, with --recursive it
+    # may happen that there are in fact no C/C++ files in a module directory
+    if not list_of_files:
+        print("No files found to check!")
+        sys.exit(-2)
+
     moduleName = sorted(list_of_files)[0].split("/")[0]
     rulePath = os.path.join(moduleName, "IwyuFilter_" + moduleName + ".yaml")
     moduleRules = {}
commit 45aac5b97192a97369c7785772ce7400d9ea8abc
Author:     Hossein <hoss...@libreoffice.org>
AuthorDate: Sun Apr 24 14:13:21 2022 +0200
Commit:     Hossein - <hoss...@libreoffice.org>
CommitDate: Sun Apr 24 14:56:24 2022 +0200

    Remove brittle test from WmfTest
    
    The WmfTest::testStockObject() contained test for the number of
    children in the metafile dump. This can be changed when unimplemented
    records are implemented.
    
    The problem was revelead while implementing SetPolyFillMode record:
    <https://ci.libreoffice.org/job/gerrit_linux_clang_dbgutil/112114/>
    
    xmltesttools.cxx:234:WmfTest::testStockObject
    equality assertion failed
    - Expected: 42
    - Actual  : 47
    - In <>, XPath '/metafile/push[2]' number of child-nodes is incorrect
    
    Change-Id: I627801b7ac535a2f0c736880d9675f3d0136136a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133353
    Tested-by: Jenkins
    Reviewed-by: Hossein - <hoss...@libreoffice.org>

diff --git a/emfio/qa/cppunit/wmf/wmfimporttest.cxx 
b/emfio/qa/cppunit/wmf/wmfimporttest.cxx
index d8a4ed82d0f0..a85876e03a7d 100644
--- a/emfio/qa/cppunit/wmf/wmfimporttest.cxx
+++ b/emfio/qa/cppunit/wmf/wmfimporttest.cxx
@@ -402,11 +402,6 @@ void WmfTest::testStockObject()
 
     CPPUNIT_ASSERT(pDoc);
 
-    //   Without the fix in place, this test would have failed with
-    // - Expected: 42
-    // - Actual  : 37
-    assertXPathChildren(pDoc, "/metafile/push[2]", 42);
-
     //   Without the fix in place, this test would have failed with
     // - Expected: 1
     // - Actual  : 0
commit 3d7466b92a450d7ca4f45fef9a664143fbb3c386
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Sat Apr 23 21:52:29 2022 +0200
Commit:     Regina Henschel <rb.hensc...@t-online.de>
CommitDate: Sun Apr 24 13:37:54 2022 +0200

    Do not start a:path with lnTo in export to OOXML
    
    This is a follow up to commit 2029b2f6dd0109c5892e5ac5640022b31fe42fd2
    
    The commands A, W, T or L of a draw:enhanced-path draw a line from
    current point to start of the arc or end of line, respectivly. If
    there is no current point the path is faulty and behavior is not
    defined in ODF.
    
    LibreOffice is tolerant and makes a move to the start point of the
    arc or to the end point of the line. With this patch we do the same
    now in export to OOXML, so the user gets the same shape geometry as in
    LO. If a path starts with lnTo, MS Office will show nothing.
    
    I wouldn't care about user-created faulty paths, but LO produces such
    faulty path when an EllipseRibbon shape from binary MS Office is
    imported. Even when that will be fixed, we need the fix here, because
    the faulty path had been written to document markup and will be used
    when such document is opened.
    
    Change-Id: Ic52ec3bc78231b26efb592ddadee2e3042fdc065
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133349
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>

diff --git a/oox/qa/unit/data/FaultyPathStart.odp 
b/oox/qa/unit/data/FaultyPathStart.odp
new file mode 100644
index 000000000000..219795ffa58b
Binary files /dev/null and b/oox/qa/unit/data/FaultyPathStart.odp differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
index b4eebc537250..7a1bda7cb5bd 100644
--- a/oox/qa/unit/export.cxx
+++ b/oox/qa/unit/export.cxx
@@ -632,6 +632,26 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf109169_OctagonBevel)
     assertXPath(pXmlDoc, "//a:pathLst/a:path[5]", "fill", "lightenLess");
     assertXPath(pXmlDoc, "//a:pathLst/a:path[6]", "fill", "lighten");
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testFaultyPathCommandsAWT)
+{
+    // The odp file contains shapes whose path starts with command A, W, T or 
L. That is a faulty
+    // path. LO is tolerant and renders it so that is makes a moveTo to the 
start point of the arc or
+    // the end of the line respectively. Export to OOXML does the same now and 
writes a moveTo
+    // instead of the normally used lnTo. If a lnTo is written, MS Office 
shows nothing of the shape.
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"FaultyPathStart.odp";
+
+    loadAndSave(aURL, "Impress Office Open XML");
+
+    // Verify the markup:
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"ppt/slides/slide1.xml");
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+    // First child of a:path should be a moveTo in all four shapes.
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[3]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[4]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 327b567c4c40..78eac3d00f60 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -4218,10 +4218,21 @@ bool DrawingML::WriteCustomGeometrySegment(
         {
             if (rnPairIndex >= rPairs.getLength())
                 return false;
-
-            mpFS->startElementNS(XML_a, XML_lnTo);
-            WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
-            mpFS->endElementNS(XML_a, XML_lnTo);
+            // LINETO without valid current point is a faulty path. LO is 
tolerant and makes a
+            // moveTo instead. Do the same on export. MS OFFICE requires a 
current point for lnTo,
+            // otherwise it shows nothing of the shape.
+            if (rbCurrentValid)
+            {
+                mpFS->startElementNS(XML_a, XML_lnTo);
+                WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
+                mpFS->endElementNS(XML_a, XML_lnTo);
+            }
+            else
+            {
+                mpFS->startElementNS(XML_a, XML_moveTo);
+                WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
+                mpFS->endElementNS(XML_a, XML_moveTo);
+            }
             rCustomShape2d.GetParameter(rfCurrentX, rPairs[rnPairIndex].First, 
false, false);
             rCustomShape2d.GetParameter(rfCurrentY, 
rPairs[rnPairIndex].Second, false, false);
             rbCurrentValid = true;
@@ -4284,7 +4295,8 @@ bool DrawingML::WriteCustomGeometrySegment(
             getEllipsePointFromViewAngle(fSx, fSy, fWR, fHR, fCx, fCy, 
fStartAngle);
 
             // write markup for going to start point
-            if (eCommand == ANGLEELLIPSETO)
+            // lnTo requires a valid current point
+            if (eCommand == ANGLEELLIPSETO && rbCurrentValid)
             {
                 mpFS->startElementNS(XML_a, XML_lnTo);
                 mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fSx)),
@@ -4347,7 +4359,8 @@ bool DrawingML::WriteCustomGeometrySegment(
             getEllipsePointAndAngleFromRayPoint(fStartAngle, fPx, fPy, fWR, 
fHR, fCx, fCy, fX3,
                                                 fY3);
             // markup for going to start point
-            if (eCommand == ARCTO || eCommand == CLOCKWISEARCTO)
+            // lnTo requires a valid current point.
+            if ((eCommand == ARCTO || eCommand == CLOCKWISEARCTO) && 
rbCurrentValid)
             {
                 mpFS->startElementNS(XML_a, XML_lnTo);
                 mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fPx)),
commit 8202df1815ed692df371e6d07a3b0f29a329f6ed
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Fri Apr 22 18:26:49 2022 +0200
Commit:     Bartosz Kosiorek <gan...@poczta.onet.pl>
CommitDate: Sun Apr 24 13:01:05 2022 +0200

    tdf#103859 EMF+ Use variable types according to EMFPLUS documentation
    
    With this commit, the types of variable for Brush and Pen
    were aligned to documentation:
    [MS-EMFPLUS] - Enhanced Metafile Format Plus Extensions
    
    As a side effect the code was simplified a bit
    
    Change-Id: Ibabad628d0aaef510f61ee8b3d881c3f024cebef
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133327
    Tested-by: Jenkins
    Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl>

diff --git a/drawinglayer/source/tools/emfpbrush.cxx 
b/drawinglayer/source/tools/emfpbrush.cxx
index 4acc311345a8..7d6204a5da9e 100644
--- a/drawinglayer/source/tools/emfpbrush.cxx
+++ b/drawinglayer/source/tools/emfpbrush.cxx
@@ -113,17 +113,12 @@ namespace emfplushelper
                 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter color: 0x" << 
std::hex << color << std::dec);
                 s.ReadFloat(firstPointX).ReadFloat(firstPointY);
                 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter point: " << 
firstPointX << "," << firstPointY);
-                s.ReadInt32(surroundColorsNumber);
+                s.ReadUInt32(surroundColorsNumber);

... etc. - the rest is truncated

Reply via email to