Rebased ref, commits from common ancestor: commit 983ea068f2a30c08964b7cbadcb8fa19a2ba8e4b Author: Jan-Marek Glogowski <glo...@fbihome.de> AuthorDate: Sun Jan 9 14:49:28 2022 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 19:51:49 2022 +0100
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 ad06e8254c89..63e37d139336 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 028986b8840447fa3a9ced8d3f866595854ff4b7 Author: Jan-Marek Glogowski <glo...@fbihome.de> AuthorDate: Wed Nov 17 01:57:33 2021 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 19:51:48 2022 +0100 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 6e87c89217f4..0f6cbeb55fdc 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 @@ class Point; struct SfxDispatcher_Impl; 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 87108359dab1..89a9d2a058c8 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 68068ab4a864..280558b2dbd1 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -1859,6 +1859,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 b0eee6eefb22..c182e67723ab 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,13 +1749,14 @@ 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; } } } -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 )), @@ -1714,16 +1765,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(); @@ -1751,14 +1815,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 859c35664fea..f6bf6da313e3 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -5427,7 +5427,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 cbeb1ef7f810..a13ced69163a 100644 --- a/toolkit/source/awt/vclxmenu.cxx +++ b/toolkit/source/awt/vclxmenu.cxx @@ -37,6 +37,7 @@ #include <vcl/window.hxx> #include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp> VCLXMenu::VCLXMenu() : maMenuListeners( *this ) @@ -492,6 +493,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 5d5ce94a9b8f..b73ad471f0d1 100644 --- a/toolkit/source/helper/unowrapper.cxx +++ b/toolkit/source/helper/unowrapper.cxx @@ -191,7 +191,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 55275ae6e099..738c98e336a3 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; @@ -52,6 +52,9 @@ private: QPushButton* mpCloseButton; QMetaObject::Connection maCloseButtonConnection; + css::uno::Reference<css::ui::dialogs::XDialogClosedListener> m_xListener; + FloatingWindow* m_pWin; + void DoFullMenuUpdate(Menu* pMenuBar); static void NativeItemText(OUString& rItemText); @@ -72,8 +75,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 c696503549e6..60840a020460 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; @@ -75,7 +76,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 d9279fb9389a..b2d050291084 100644 --- a/vcl/qt5/QtMenu.cxx +++ b/vcl/qt5/QtMenu.cxx @@ -93,6 +93,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) @@ -672,15 +682,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 e19d055b8253..2362838a1396 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -176,7 +176,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 2fd136429061..f7055dbf92f4 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -2657,6 +2657,7 @@ MenuFloatingWindow * PopupMenu::ImplGetFloatingWindow() const { } PopupMenu::PopupMenu() + : m_pState(nullptr) { mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu(false, this); } @@ -2669,6 +2670,7 @@ PopupMenu::PopupMenu( const PopupMenu& rMenu ) PopupMenu::~PopupMenu() { + assert(!m_pState); disposeOnce(); } @@ -2766,6 +2768,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? @@ -2917,7 +2949,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 ) { @@ -2933,10 +2965,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); @@ -2972,7 +3005,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; } @@ -3017,11 +3055,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 7e3b66c48ff80aa9f415e007e580ec520ccc6b8f Author: Jan-Marek Glogowski <glo...@fbihome.de> AuthorDate: Sat Nov 20 15:06:35 2021 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 19:51:48 2022 +0100 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 a6699a7e71d9..87108359dab1 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 6af85523f8a1..2fd136429061 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -2742,10 +2742,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; @@ -2759,7 +2757,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() @@ -2775,10 +2779,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(); @@ -2790,7 +2798,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; @@ -2806,25 +2813,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 ) @@ -2854,10 +2860,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()); } @@ -2876,9 +2882,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(); @@ -2893,8 +2899,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(); @@ -2909,7 +2915,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; @@ -2921,43 +2927,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 @@ -2968,22 +2965,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 ) @@ -2992,13 +2997,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 49f7265efc8a1459498300b93ec899e572b1edc2 Author: Thorsten Behrens <thorsten.behr...@allotropia.de> AuthorDate: Sat Nov 13 23:12:58 2021 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 19:51:48 2022 +0100 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 e6771b6d08f7..ff5e2e12603d 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -6501,7 +6501,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(); } } @@ -6540,7 +6544,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 d778aa1d0ecc2127a4968fc4f88e9cbf5a8be451 Author: Jan-Marek Glogowski <glo...@fbihome.de> AuthorDate: Mon Dec 6 09:24:50 2021 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 19:51:48 2022 +0100 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 5c164d73729d..f0ce0774d756 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 \ @@ -580,6 +580,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 5b886ea2189d..e1fcf84c255f 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 7fc1cd79c12d..eeba150d0275 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 dcfa05337843..7f7363ebb85c 100644 --- a/solenv/gbuild/gbuild.mk +++ b/solenv/gbuild/gbuild.mk @@ -283,6 +283,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 c70e3ce222bb..9ca593154d38 100644 --- a/solenv/gbuild/platform/unxgcc.mk +++ b/solenv/gbuild/platform/unxgcc.mk @@ -313,12 +313,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 0e97584cacec5ef6efb857a5fdf0e6f4ca33382c Author: Jan-Marek Glogowski <glo...@fbihome.de> AuthorDate: Sat Jan 8 22:53:29 2022 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 19:51:48 2022 +0100 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 300469aa0d5e..015fa183fd66 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 d2f37bb549a7..217e2119ad2c 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> @@ -64,7 +66,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). @@ -74,7 +85,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 12a6b57c74aa555ab15de84c58d4698a14881752 Author: Jan-Marek Glogowski <glo...@fbihome.de> AuthorDate: Mon Jan 10 04:50:03 2022 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 19:49:55 2022 +0100 WASM update README.wasm.md Change-Id: Ic38a7a0637ab007f12a6046655cb7d36e24fae33 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128655 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <glo...@fbihome.de> diff --git a/static/README.wasm.md b/static/README.wasm.md index bfe930ef6775..ccc7a5b8aec7 100644 --- a/static/README.wasm.md +++ b/static/README.wasm.md @@ -4,23 +4,20 @@ This module provides support for emscripten cross build ## Status - $ make +The build generates a Writer-only LO build. You should be able to run either -You can run the WASM mandelbrot Qt example, if you copy its HTML -and the qtloader.js from the Qt's example folder after build with: - - $ emrun --serve_after_close workdir/LinkTarget/Executable/mandelbrot.html + $ emrun --serve_after_close instdir/program/qt_soffice.html + $ emrun --serve_after_close workdir/LinkTarget/Executable/qt_vcldemo.html + $ emrun --serve_after_close workdir/LinkTarget/Executable/qt_wasm-qt5-mandelbrot.html REMINDER: Always start new tabs in the browser, reload might fail / cache! - +INFO: latest browser won't work anymore with 0.0.0.0 and need 127.0.0.1. ## Setup for the LO WASM build (with Qt) -We're using Qt 5.15 with the officially supported emscripten v1.39.8. -But there are several potential problems with threads and exceptions, so this will likely -change later to a newer emscripten. - -Qt WASM is not yet used with LO, just if you're wondering! +We're using Qt 5.15.2 with Emscripten 2.0.31. There are a bunch of Qt patches +to fix the most grave bugs. Also newer Emscripten versions have various bugs +with the FS image support. - See below under Docker build for another build option @@ -29,8 +26,8 @@ Qt WASM is not yet used with LO, just if you're wondering! <https://emscripten.org/docs/getting_started/index.html> git clone https://github.com/emscripten-core/emsdk.git - ./emsdk install 1.39.8 - ./emsdk activate --embedded 1.39.8 + ./emsdk install 2.0.31 + ./emsdk activate --embedded 2.0.31 Example `bashrc` scriptlet: @@ -41,41 +38,54 @@ Example `bashrc` scriptlet: <https://doc.qt.io/qt-5/wasm.html> -I originally build the Qt 5.15 branch, but probably better to build a tag like v5.15.2. +Most of the information from <https://doc.qt.io/qt-6/wasm.html> is still valid for Qt5; +generally the Qt6 WASM documentation is much better, because it incorporated many +information from the Qt Wiki. + +FWIW: Qt 5.15 LTS is not maintained publically and Qt WASM has quite a few bugs. Most +WASM fixes from Qt 6 are needed for Qt 5.15 too. They can mainly be cherry-picked from: +- git log origin/dev src/plugins/platforms/wasm/ +- git log --grep wasm origin/dev -So: +We will probably offer our own Qt repository clone at some point. + +But even the public Qt 5.15 branch is still broken, so better start with the v5.15.2 tag. git clone https://github.com/qt/qt5.git cd qt5 git checkout v5.15.2 - ./init-repository - ./configure -xplatform wasm-emscripten -feature-thread -compile-examples -prefix $PWD/qtbase - make -j<CORES> module-qtbase module-qtdeclarative - + ./init-repository --module-subset=qtbase + ./configure -xplatform wasm-emscripten -feature-thread -prefix $PWD/install-5.15.2 + make -j<CORES> module-qtbase + +Optionally you can add the configure flag "-compile-examples". But then you also have to +patch at least mkspecs/wasm-emscripten/qmake.conf with EXIT_RUNTIME=0, otherwise they will +fail to run. In addition, building with examples will break with some of them, but at that +point Qt already works and also most examples. Building with examples will break with some of them, but at that point Qt already works. +Or just skip them. Other interesting flags might be "-nomake tests -no-pch -ccache". -At some point Qt configure failed for me with: +Linking takes quite a long time, because emscripten-finalize rewrites the whole WASM files +with some options. This way the LO WASM needs at least 64GB RAM. For faster link times add +"-s WASM_BIGINT=1", change to ASSERTIONS=1 nd use -g3 to prevent rewriting the WASM file +and generating source maps (see emscripten.py, finalize_wasm, and avoid modify_wasm = True). +This is just needed for Qt examples, as LO already uses the correct flags! -"Checking for target architecture... Project ERROR: target architecture detection binary not found." +The install is not really needed, as LO currently just uses qtbase on it's own. You can do -What seems to have fixed this was to run "emsdk activate 1.39.8" again. + make -j<CORES> install +or + make -j8 -C qtbase/src install_subtargets Current Qt fails to start the demo webserver: <https://bugreports.qt.io/browse/QTCREATORBUG-24072> -Use `emrun --serve_after_close` to run Qt WASM demos - -Enabling multi-thread support in Firefox is a bit of work with older versions: - -- <https://bugzilla.mozilla.org/show_bug.cgi?id=1477743#c7> -- <https://wiki.qt.io/Qt_for_WebAssembly#Multithreading_Support> -- <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer> - +Use `emrun --serve_after_close` to run Qt WASM demos. ### Setup LO -`autogen.sh` is patched to use emconfigure. That basically sets various environment vars, -especially `EMMAKEN_JUST_CONFIGURE`, which will create the correct output file names, checked by -`configure` (`a.out`). +`autogen.sh` is patched to use emconfigure. That basically sets various +environment vars, especially `EMMAKEN_JUST_CONFIGURE`, which will create the +correct output file names, checked by `configure` (`a.out`). There's a distro config for WASM (work in progress), that gets your defaults right (and currently disables a ton of 3rd party stuff which @@ -93,6 +103,35 @@ Recommended configure setup is thusly: `--with-build-platform-configure-options=--enable-ccache` `--enable-ccache` +FWIW: it's also possible to build an almost static Linux LibreOffice by just using +--disable-dynloading --enable-customtarget-components. System externals are still +linked dynamically, but everything else is static. + +### "Deploying" soffice.wasm + + tar -chf wasm.tar --xform 's/.*program/lo-wasm/' instdir/program/soffice.* \ + instdir/program/qt* + +Your HTTP server needs to provide aditional headers: +* add_header Cross-Origin-Opener-Policy same-origin +* add_header Cross-Origin-Embedder-Policy require-corp + +The default html to use should be qt_soffice.html + +### Debugging setup + +Since a few months you can use DWARF information embedded by LLVM into the WASM +to debug WASM in Chrome. You need to enable an experimental feature and install +an additional extension. The whole setup is described in: + +https://developer.chrome.com/blog/wasm-debugging-2020/ + +This way you don't need source maps (much faster linking!) and can resolve local +WASM variables to C++ names! + +Per default, the WASM debug build splits the DWARF information into an additional +WASM file, postfixed '.debug.wasm'. + ### Using Docker to cross-build with emscripten If you prefer a controlled environment (sadly emsdk install/activate @@ -109,7 +148,8 @@ Run in the lode/docker dir to get the container prepared. Run - PARALLELISM=4 BUILD_OPTIONS= BUILD_TARGET=build docker-compose run --rm -e PARALLELISM -e BUILD_TARGET -e BUILD_OPTIONS builder + PARALLELISM=4 BUILD_OPTIONS= BUILD_TARGET=build docker-compose run --rm \ + -e PARALLELISM -e BUILD_TARGET -e BUILD_OPTIONS builder to perform an actual `srcdir != builddir` build; the container mounts checked-out git repo and output dir via `docker-compose.yml` (so make @@ -152,27 +192,6 @@ WASM dynamic dispatch: - <https://fitzgeraldnick.com/2018/04/26/how-does-dynamic-dispatch-work-in-wasm.html> - -## Workaround for eventual clang WASM compiler bug - -```` -sc/source/core/data/attarray.cxx:378:44: error: call to member function 'erase' is ambiguous - aNewCondFormatData.erase(nIndex); - ~~~~~~~~~~~~~~~~~~~^~~~~ -include/o3tl/sorted_vector.hxx:86:15: note: candidate function - size_type erase( const Value& x ) - ^ -include/o3tl/sorted_vector.hxx:97:10: note: candidate function - void erase( size_t index ) -```` - -This is currently patched by using `x.erase` (`x.begin() + nIndex`). - -There shouldn't be an ambiguity, because of "[WebAssembly] Change size_t to `unsigned long`." -<https://reviews.llvm.org/rGdf07a35912d78781ed6a62a7c032bfef5085a4f5#change-IrS9f6jH6PFq>, -from "Jul 23 2018" which pre-dates the emscripten tag 1.39.8 from 02/14/2020 by ~1.5y. - - ## Tools for problem diagnosis * `nm -s` should list the symbols in the archive, based on the index generated by ranlib. @@ -185,7 +204,6 @@ This is closed, but not really fixed IMHO: - <https://github.com/emscripten-core/emscripten/issues/3922> - ## Dynamic libraries `/` modules in emscripten There is a good summary in: commit 1ad8c5066bdb6ea825ad09d2a6c7f633b974fc69 Author: Jan-Marek Glogowski <glo...@fbihome.de> AuthorDate: Thu Jan 20 16:09:38 2022 +0100 Commit: Jan-Marek Glogowski <glo...@fbihome.de> CommitDate: Thu Jan 20 18:37:08 2022 +0100 Sorting component implementations needs LC_ALL=C Change-Id: Ifba53b95fdefed59123a2e682e787119b6c67857 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128689 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <glo...@fbihome.de> diff --git a/config_host.mk.in b/config_host.mk.in index 9a0388fa0d35..193406c8fbc9 100644 --- a/config_host.mk.in +++ b/config_host.mk.in @@ -685,6 +685,7 @@ export TOUCH=@TOUCH@ export UCRTSDKDIR=@UCRTSDKDIR@ export UCRTVERSION=@UCRTVERSION@ export UCRT_REDISTDIR=@UCRT_REDISTDIR@ +export UNIQ=@UNIQ@ export UNIX_DLAPI_LIBS=@UNIX_DLAPI_LIBS@ export USE_HEADLESS_CODE=@USE_HEADLESS_CODE@ export USE_LD=@USE_LD@ diff --git a/configure.ac b/configure.ac index 751ad1ebb872..53b2323a2c09 100644 --- a/configure.ac +++ b/configure.ac @@ -11415,6 +11415,12 @@ if test -z "$DIFF"; then fi AC_SUBST([DIFF]) +AC_PATH_PROG(UNIQ, uniq) +if test -z "$UNIQ"; then + AC_MSG_ERROR(["uniq" not found in \$PATH, install it]) +fi +AC_SUBST([UNIQ]) + dnl *************************************** dnl Checking for patch dnl *************************************** diff --git a/solenv/gbuild/ComponentTarget.mk b/solenv/gbuild/ComponentTarget.mk index ce0224433661..aed3fd88e889 100644 --- a/solenv/gbuild/ComponentTarget.mk +++ b/solenv/gbuild/ComponentTarget.mk @@ -62,18 +62,18 @@ $(call gb_ComponentTarget_get_target,%).optionals : \ | $(call gb_ComponentTarget_get_target,%).dir \ $(call gb_ExternalExecutable_get_dependencies,xsltproc) $(call gb_ExternalExecutable_get_command,xsltproc) --nonet \ - $(gb_ComponentTarget_XSLT_DUMP_OPTIONALS) $(COMPONENTSOURCE) 2>&1 | sort > $@ + $(gb_ComponentTarget_XSLT_DUMP_OPTIONALS) $(COMPONENTSOURCE) 2>&1 | LC_ALL=C $(SORT) > $@ # %.filtered : list of all optional implementations we don't build .PRECIOUS: $(call gb_ComponentTarget_get_target,%).filtered $(call gb_ComponentTarget_get_target,%).filtered : $(call gb_ComponentTarget_get_target,%).optionals - cat $< $(COMPONENTIMPL) | sed -e '/^#/d' -e '/^[ ]*$$/d' | sort | uniq -u > $@ + cat $< $(COMPONENTIMPL) | sed -e '/^#/d' -e '/^[ ]*$$/d' | LC_ALL=C $(SORT) | $(UNIQ) -u > $@ # %.allfiltered : contains all possible filtered components, which must match %.optionals .PRECIOUS: $(call gb_ComponentTarget_get_target,%).allfiltered $(call gb_ComponentTarget_get_target,%).allfiltered : $(call gb_ComponentTarget_get_target,%).optionals $(if $(ALLFILTEREDIMPL), \ - cat $(ALLFILTEREDIMPL) | sed -e '/^#/d' -e '/^[ ]*$$/d' | sort | uniq > $@.tmp, \ + cat $(ALLFILTEREDIMPL) | sed -e '/^#/d' -e '/^[ ]*$$/d' | LC_ALL=C $(SORT) -u > $@.tmp, \ touch $@.tmp) $(DIFF) -u $< $@.tmp mv $@.tmp $@ commit 493d3558c6e6dce980cb92434f72c0ad03487aa0 Author: Andrea Gelmini <andrea.gelm...@gelma.net> AuthorDate: Thu Jan 20 15:33:13 2022 +0100 Commit: Julien Nabet <serval2...@yahoo.fr> CommitDate: Thu Jan 20 17:34:36 2022 +0100 Fix typo Thanks a lot to Valter Mura: https://listarchives.libreoffice.org/global/l10n/2022/msg00005.html Change-Id: I37467e1b9ba7cba2553be5df0d8324da8fe6c13b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128303 Tested-by: Jenkins Reviewed-by: Julien Nabet <serval2...@yahoo.fr> diff --git a/config_host/config_global.h.in b/config_host/config_global.h.in index 5f24fe8da397..40b804a60f77 100644 --- a/config_host/config_global.h.in +++ b/config_host/config_global.h.in @@ -35,7 +35,7 @@ Any change in this header will cause a rebuild of almost everything. <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87150> "move ctor wrongly chosen in return stmt (derived vs. base)"; MSVC++ 14.24 started to implement it, see <https:// developercommunity.visualstudio.com/content/problem/852827/ - msvc-1424-started-to-chose-move-ctor-in-return-der.html> "MSVC++ 14.24 started to chose move ctor + msvc-1424-started-to-chose-move-ctor-in-return-der.html> "MSVC++ 14.24 started to choose move ctor in return derived vs. base". At least Clang 9, which does not implement it, emits -Werror,-Wreturn-std-move when it therefore considers a std::move to be missing. On the other hand, at least some versions of GCC would emit -Werror=redundant-move in places where such a diff --git a/extensions/source/propctrlr/formcomponenthandler.hxx b/extensions/source/propctrlr/formcomponenthandler.hxx index 79b83fb927ed..bc7367abbeae 100644 --- a/extensions/source/propctrlr/formcomponenthandler.hxx +++ b/extensions/source/propctrlr/formcomponenthandler.hxx @@ -255,7 +255,7 @@ namespace pcr */ bool impl_dialogFilterOrSort_nothrow( bool _bFilter, OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; - /** executes a dialog which allows the user to chose the columns linking + /** executes a dialog which allows the user to choose the columns linking a sub to a master form, and sets the respective MasterFields / SlaveFields properties at the form. @precond diff --git a/include/formula/grammar.hxx b/include/formula/grammar.hxx index b5b499d5aab4..677087d19934 100644 --- a/include/formula/grammar.hxx +++ b/include/formula/grammar.hxx @@ -33,7 +33,7 @@ class FORMULA_DLLPUBLIC FormulaGrammar { public: enum AddressConvention{ - CONV_UNSPECIFIED = -1, /* useful when we want method to chose, must be first */ + CONV_UNSPECIFIED = -1, /* useful when we want method to choose, must be first */ /* elements must be sequential and changes should be reflected in ScCompiler::pCharTables */ CONV_OOO = 0, /* 'doc'#sheet.A1:sheet2.B2 */ diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx index 2170f78907ed..62c9be0344e5 100644 --- a/include/svx/svdmodel.hxx +++ b/include/svx/svdmodel.hxx @@ -279,7 +279,7 @@ public: // If you do use a custom Pool, make sure you inherit from SdrItemPool, // if you want to use symbol objects inherited from SdrAttrObj. // If, however, you use objects inheriting from SdrObject you are free - // to chose a pool of your liking. + // to choose a pool of your liking. // // tdf#118731 a bDisablePropertyFiles of true will disable ability to load // XPropertyFiles describing defaults. Useful for UI preview widgets diff --git a/offapi/com/sun/star/chart2/XChartDocument.idl b/offapi/com/sun/star/chart2/XChartDocument.idl index 0055cbb83fd2..484d4c256a94 100644 --- a/offapi/com/sun/star/chart2/XChartDocument.idl +++ b/offapi/com/sun/star/chart2/XChartDocument.idl @@ -42,7 +42,7 @@ interface XChartDocument : ::com::sun::star::frame::XModel <p>Notes: this is preliminary, we need an API that supports more than one diagram. The method name getDiagram exists in - the css.chart API, so there is would be no way to chose either + the css.chart API, so there is would be no way to choose either this or the other method from Basic (it would chose one or the other by random).</p> */ @@ -52,7 +52,7 @@ interface XChartDocument : ::com::sun::star::frame::XModel <p>Notes: this is preliminary, we need an API that supports more than one diagram. The method name setDiagram exists in - the css.chart API, so there is would be no way to chose either + the css.chart API, so there is would be no way to choose either this or the other method from Basic (it would chose one or the other by random).</p> */ diff --git a/offapi/com/sun/star/ucb/XFileIdentifierConverter.idl b/offapi/com/sun/star/ucb/XFileIdentifierConverter.idl index 0f210ea1251b..618cfa33bf4d 100644 --- a/offapi/com/sun/star/ucb/XFileIdentifierConverter.idl +++ b/offapi/com/sun/star/ucb/XFileIdentifierConverter.idl @@ -33,7 +33,7 @@ published interface XFileIdentifierConverter : com::sun::star::uno::XInterface { /** Get information about the "locality" of a file content provider. - <p>The returned information can be used to chose the "best" among a + <p>The returned information can be used to choose the "best" among a number of file content providers implementing this interface. @param BaseURL commit a557830dea9c287b11f3e610778acab94d03cdb0 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Jan 18 16:07:47 2022 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Thu Jan 20 17:11:56 2022 +0100 centralize these GetTextArray uses no logic change intended Change-Id: Ide0a6afc30690d05647acf9bf1a0eccf72a9e60c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128570 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/sw/source/core/inc/fntcache.hxx b/sw/source/core/inc/fntcache.hxx index 0bdc4757d9b3..4285165a3336 100644 --- a/sw/source/core/inc/fntcache.hxx +++ b/sw/source/core/inc/fntcache.hxx @@ -66,13 +66,13 @@ extern SwFntObj *pLastFont; */ struct SwTextGlyphsKey { - VclPtr<OutputDevice> m_pOutputDevice; + VclPtr<const OutputDevice> m_pOutputDevice; OUString m_aText; sal_Int32 m_nIndex; sal_Int32 m_nLength; size_t mnHashCode; - SwTextGlyphsKey(VclPtr<OutputDevice> const& pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength); + SwTextGlyphsKey(const OutputDevice* pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength); bool operator==(SwTextGlyphsKey const & rhs) const; }; struct SwTextGlyphsKeyHash @@ -113,6 +113,10 @@ class SwFntObj final : public SwCacheObj /// Cache of already calculated layout glyphs and text widths. SwTextGlyphsMap m_aTextGlyphs; + void GetTextArray(const OutputDevice& rOutputDevice, const OUString& rStr, + std::vector<sal_Int32>& rDXAry, sal_Int32 nIndex, sal_Int32 nLen, + bool bCaching); + static tools::Long s_nPixWidth; static MapMode *s_pPixMap; diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index cb68f6535635..2c5f81a63390 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -77,11 +77,11 @@ static vcl::DeleteOnDeinit< VclPtr<OutputDevice> > s_pFntObjPixOut {}; * Defines a substring on a given output device, to be used as an std::unordered_map<> * key. */ -SwTextGlyphsKey::SwTextGlyphsKey(VclPtr<OutputDevice> const& pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength) +SwTextGlyphsKey::SwTextGlyphsKey(const OutputDevice* pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength) : m_pOutputDevice(pOutputDevice), m_aText(sText), m_nIndex(nIndex), m_nLength(nLength) { mnHashCode = 0; - o3tl::hash_combine(mnHashCode, pOutputDevice.get()); + o3tl::hash_combine(mnHashCode, pOutputDevice); o3tl::hash_combine(mnHashCode, m_nIndex); o3tl::hash_combine(mnHashCode, m_nLength); if(m_nLength >= 0 && m_nIndex >= 0 && m_nIndex + m_nLength <= m_aText.getLength()) @@ -899,6 +899,18 @@ namespace } } +void SwFntObj::GetTextArray(const OutputDevice& rDevice, const OUString& rStr, std::vector<sal_Int32>& rDXAry, + sal_Int32 nIndex, sal_Int32 nLen, bool bCaching) +{ + SalLayoutGlyphs* pLayoutCache = nullptr; + if (bCaching) + { + SwTextGlyphsKey aGlyphsKey{&rDevice, rStr, nIndex, nLen}; + pLayoutCache = GetCachedSalLayoutGlyphs(aGlyphsKey); + } + rDevice.GetTextArray(rStr, &rDXAry, nIndex, nLen, nullptr, pLayoutCache); +} + void SwFntObj::DrawText( SwDrawTextInfo &rInf ) { OSL_ENSURE( rInf.GetShell(), "SwFntObj::DrawText without shell" ); @@ -1075,11 +1087,11 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) std::vector<sal_Int32> aKernArray; if ( m_pPrinter ) - m_pPrinter->GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); else - rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); // Change the average width per character to an appropriate grid width // basically get the ratio of the avg width to the grid unit width, then @@ -1182,11 +1194,11 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) std::vector<sal_Int32> aKernArray; if ( m_pPrinter ) - m_pPrinter->GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); else - rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); if ( bSwitchH2V ) rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos ); if ( rInf.GetSpace() || rInf.GetKanaComp()) @@ -1322,8 +1334,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) if( rInf.GetSpace() || rInf.GetKanaComp() ) { std::vector<sal_Int32> aKernArray; - rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); if( bStretch ) { @@ -1540,10 +1552,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // get screen array std::vector<sal_Int32> aScrArray; - SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; - SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); - rInf.GetOut().GetTextArray( rInf.GetText(), &aScrArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); + GetTextArray(rInf.GetOut(), rInf.GetText(), aScrArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), true); // OLE: no printer available // OSL_ENSURE( pPrinter, "DrawText needs pPrinter" ) @@ -1555,16 +1565,14 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) ) m_pPrinter->SetFont( *m_pPrtFont ); } - aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; - pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); - m_pPrinter->GetTextArray(rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); + GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), true); } else { #ifndef NDEBUG - rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); assert(aKernArray == aScrArray); #endif aKernArray = aScrArray; @@ -1876,8 +1884,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) sal_Int32 nTmpIdx = bBullet ? (rInf.GetIdx() ? 1 : 0) : sal_Int32(rInf.GetIdx()); - aGlyphsKey = SwTextGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen }; - pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); + SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen }; + SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, aKernArray, nTmpIdx , nLen, SalLayoutFlags::NONE, pGlyphs ); if (bBullet) @@ -2038,8 +2046,8 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) ) rInf.GetOut().SetFont( *m_pScrFont ); - m_pPrinter->GetTextArray(rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(nLn)); + GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(nLn), false); if( bCompress ) rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( aKernArray.data(), rInf.GetIdx(), nLn, rInf.GetKanaComp(), @@ -2057,8 +2065,8 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) if (eGlyphPositioningMode == GlyphPositioningMode::Classic) { std::vector<sal_Int32> aScrArray; - rInf.GetOut().GetTextArray( rInf.GetText(), &aScrArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + GetTextArray(rInf.GetOut(), rInf.GetText(), aScrArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); tools::Long nScrPos = aScrArray[ 0 ]; TextFrameIndex nCnt(rInf.GetText().getLength()); if ( nCnt < rInf.GetIdx() ) @@ -2094,8 +2102,8 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) if( bCompress ) { std::vector<sal_Int32> aKernArray; - rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(nLn)); + GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(nLn), false); rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( aKernArray.data(), rInf.GetIdx(), nLn, rInf.GetKanaComp(), o3tl::narrowing<sal_uInt16>(m_aFont.GetFontSize().Height()) ,lcl_IsFullstopCentered( rInf.GetOut() ) ) ); @@ -2137,14 +2145,14 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) { m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() ); m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() ); - SwTextGlyphsKey aGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; - SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); - m_pPrinter->GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); + GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), true); } else - rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + { + GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); + } const SwScriptInfo* pSI = rInf.GetScriptInfo(); if ( rInf.GetFont() && rInf.GetLen() ) commit 96607133f4457b31ddaee5808c04e96243ed99c6 Author: Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de> AuthorDate: Thu Jan 20 13:05:39 2022 +0100 ... etc. - the rest is truncated