[Libreoffice-commits] core.git: include/sfx2 include/svtools include/svx include/vcl sfx2/source svtools/source svx/source svx/uiconfig svx/UIConfig_svx.mk vcl/source vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Fri Jan 10 14:14:23 UTC 2020


 include/sfx2/weldutils.hxx                              |    1 
 include/svtools/popupwindowcontroller.hxx               |    6 -
 include/svtools/toolbarmenu.hxx                         |   31 +++++
 include/svx/ParaLineSpacingPopup.hxx                    |    1 
 include/svx/tbcontrl.hxx                                |    2 
 include/vcl/weld.hxx                                    |    8 -
 sfx2/source/toolbox/weldutils.cxx                       |   10 +
 svtools/source/control/toolbarmenu.cxx                  |   48 ++++++++-
 svtools/source/uno/popupwindowcontroller.cxx            |   27 ++++-
 svx/UIConfig_svx.mk                                     |    1 
 svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx |    4 
 svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx |    2 
 svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx   |   32 ++----
 svx/source/tbxctrls/bulletsnumbering.cxx                |   34 +++---
 svx/source/tbxctrls/tbcontrl.cxx                        |   84 ++++++++--------
 svx/uiconfig/ui/colorwindow.ui                          |    2 
 svx/uiconfig/ui/toolbarpopover.ui                       |   21 ++++
 vcl/source/app/salvtables.cxx                           |   37 ++++++-
 vcl/unx/gtk3/gtk3gtkinst.cxx                            |   20 ++-
 19 files changed, 267 insertions(+), 104 deletions(-)

New commits:
commit 14e26096f0476b8ecb70511c304a0cdf5440ef7a
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Thu Jan 9 15:45:46 2020 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Fri Jan 10 15:13:45 2020 +0100

    make welded toolbars on-demand that were previously on-demand
    
    Change-Id: I795723260deb317093e83d951d968e0b3d3a1850
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86531
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/include/sfx2/weldutils.hxx b/include/sfx2/weldutils.hxx
index cfcf545d9002..2486ca97307e 100644
--- a/include/sfx2/weldutils.hxx
+++ b/include/sfx2/weldutils.hxx
@@ -33,6 +33,7 @@ private:
     weld::Toolbar* m_pToolbar;
 
     DECL_LINK(SelectHdl, const OString&, void);
+    DECL_LINK(ToggleMenuHdl, const OString&, void);
 
     void CreateController(const OUString& rCommand);
 
diff --git a/include/svtools/popupwindowcontroller.hxx b/include/svtools/popupwindowcontroller.hxx
index be39cc8e2b69..f1df441a4979 100644
--- a/include/svtools/popupwindowcontroller.hxx
+++ b/include/svtools/popupwindowcontroller.hxx
@@ -33,6 +33,7 @@
 namespace vcl { class Window; }
 
 class InterimToolbarPopup;
+class ToolbarPopupContainer;
 class WeldToolbarPopup;
 
 namespace svt
@@ -46,11 +47,13 @@ public:
     PopupWindowController( const css::uno::Reference< css::uno::XComponentContext >& rxContext,
                            const css::uno::Reference< css::frame::XFrame >& xFrame,
                            const OUString& aCommandURL );
+
     virtual ~PopupWindowController() override;
 
     void EndPopupMode();
 
     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) = 0;
+    virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow();
 
     // XServiceInfo
     virtual OUString SAL_CALL getImplementationName() override = 0;
@@ -65,9 +68,10 @@ public:
 
     // XToolbarController
     virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override;
+    virtual void SAL_CALL click() override;
 
 protected:
-    std::unique_ptr<WeldToolbarPopup> mxPopover;
+    std::unique_ptr<ToolbarPopupContainer> mxPopoverContainer;
     VclPtr<InterimToolbarPopup> mxInterimPopover;
 
 private:
diff --git a/include/svtools/toolbarmenu.hxx b/include/svtools/toolbarmenu.hxx
index 1ff5079e569a..f06611817797 100644
--- a/include/svtools/toolbarmenu.hxx
+++ b/include/svtools/toolbarmenu.hxx
@@ -173,16 +173,41 @@ public:
     virtual void GrabFocus() = 0;
 };
 
+// we want to create WeldToolbarPopup on-demand when a toolbar dropdown is
+// clicked, but the widget to be shown must exist before the dropdown
+// is activated, so ToolbarPopupContainer is that widget and the
+// contents of the on-demand created WeldToolbarPopup is placed
+// within the ToolbarPopupContainer
+class SVT_DLLPUBLIC ToolbarPopupContainer
+{
+private:
+    DECL_LINK(FocusHdl, weld::Widget&, void);
+
+protected:
+    std::unique_ptr<weld::Builder> m_xBuilder;
+    std::unique_ptr<weld::Container> m_xTopLevel;
+    std::unique_ptr<weld::Container> m_xContainer;
+    std::unique_ptr<WeldToolbarPopup> m_xPopup;
+public:
+    ToolbarPopupContainer(weld::Widget* pParent);
+    ~ToolbarPopupContainer();
+    weld::Container* getTopLevel() { return m_xTopLevel.get(); }
+    weld::Container* getContainer() { return m_xContainer.get(); }
+
+    void setPopover(std::unique_ptr<WeldToolbarPopup> xPopup);
+    void unsetPopover();
+};
+
 class SVT_DLLPUBLIC InterimToolbarPopup : public svtools::ToolbarPopup
 {
 protected:
     VclPtr<vcl::Window> m_xBox;
     std::unique_ptr<weld::Builder> m_xBuilder;
     std::unique_ptr<weld::Container> m_xContainer;
-
-    WeldToolbarPopup* m_pPopup;
+    std::unique_ptr<WeldToolbarPopup> m_xPopup;
 public:
-    InterimToolbarPopup(const css::uno::Reference<css::frame::XFrame>& rFrame, vcl::Window* pParent, WeldToolbarPopup* pPopup);
+    InterimToolbarPopup(const css::uno::Reference<css::frame::XFrame>& rFrame, vcl::Window* pParent,
+                        std::unique_ptr<WeldToolbarPopup> xPopup);
     weld::Container* getContainer() { return m_xContainer.get(); }
     virtual void dispose() override;
     virtual ~InterimToolbarPopup() override;
diff --git a/include/svx/ParaLineSpacingPopup.hxx b/include/svx/ParaLineSpacingPopup.hxx
index 743894ce31e0..4d22cdc8bd2c 100644
--- a/include/svx/ParaLineSpacingPopup.hxx
+++ b/include/svx/ParaLineSpacingPopup.hxx
@@ -34,6 +34,7 @@ public:
 
     using svt::ToolboxController::createPopupWindow;
     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) override;
+    virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
 
     // XServiceInfo
     virtual OUString SAL_CALL getImplementationName() override;
diff --git a/include/svx/tbcontrl.hxx b/include/svx/tbcontrl.hxx
index 226160e422c0..e812ce4685d8 100644
--- a/include/svx/tbcontrl.hxx
+++ b/include/svx/tbcontrl.hxx
@@ -231,6 +231,7 @@ public:
 
     using svt::ToolboxController::createPopupWindow;
     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) override;
+    virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
 
     // XSubToolbarController
     virtual sal_Bool SAL_CALL opensSubToolbar() override;
@@ -279,6 +280,7 @@ public:
 
     using svt::ToolboxController::createPopupWindow;
     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) override;
+    virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
 
     // XServiceInfo
     virtual OUString SAL_CALL getImplementationName() override;
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index e205ea2459c6..6d99c3516589 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -1956,10 +1956,10 @@ class VCL_DLLPUBLIC Toolbar : virtual public Widget
 {
 protected:
     Link<const OString&, void> m_aClickHdl;
-    Link<const OString&, void> m_aShowMenuHdl;
+    Link<const OString&, void> m_aToggleMenuHdl;
 
     void signal_clicked(const OString& rIdent) { m_aClickHdl.Call(rIdent); }
-    void signal_show_menu(const OString& rIdent) { m_aShowMenuHdl.Call(rIdent); }
+    void signal_toggle_menu(const OString& rIdent) { m_aToggleMenuHdl.Call(rIdent); }
 
 public:
     virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) = 0;
@@ -1997,9 +1997,7 @@ public:
     virtual vcl::ImageType get_icon_size() const = 0;
 
     void connect_clicked(const Link<const OString&, void>& rLink) { m_aClickHdl = rLink; }
-    // m_aShowMenuHdl is called before the menu is shown.
-    // It can be used to populate the menu on demand with set_item_popover/set_item_menu
-    void connect_show_menu(const Link<const OString&, void>& rLink) { m_aShowMenuHdl = rLink; }
+    void connect_menu_toggled(const Link<const OString&, void>& rLink) { m_aToggleMenuHdl = rLink; }
 };
 
 class VCL_DLLPUBLIC SizeGroup
diff --git a/sfx2/source/toolbox/weldutils.cxx b/sfx2/source/toolbox/weldutils.cxx
index 52cf254d7b9a..112f285297c5 100644
--- a/sfx2/source/toolbox/weldutils.cxx
+++ b/sfx2/source/toolbox/weldutils.cxx
@@ -58,6 +58,7 @@ ToolbarUnoDispatcher::ToolbarUnoDispatcher(weld::Toolbar& rToolbar,
     , m_pToolbar(&rToolbar)
 {
     rToolbar.connect_clicked(LINK(this, ToolbarUnoDispatcher, SelectHdl));
+    rToolbar.connect_menu_toggled(LINK(this, ToolbarUnoDispatcher, ToggleMenuHdl));
 
     OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(rFrame));
     vcl::ImageType eSize = rToolbar.get_icon_size();
@@ -111,6 +112,15 @@ IMPL_LINK(ToolbarUnoDispatcher, SelectHdl, const OString&, rCommand, void)
         xController->execute(0);
 }
 
+IMPL_LINK(ToolbarUnoDispatcher, ToggleMenuHdl, const OString&, rCommand, void)
+{
+    css::uno::Reference<css::frame::XToolbarController> xController(
+        GetControllerForCommand(OUString::fromUtf8(rCommand)));
+
+    if (xController.is())
+        xController->click();
+}
+
 void ToolbarUnoDispatcher::dispose()
 {
     if (!m_pToolbar)
diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx
index 7b12d910a81e..7d74380a2d10 100644
--- a/svtools/source/control/toolbarmenu.cxx
+++ b/svtools/source/control/toolbarmenu.cxx
@@ -1537,27 +1537,65 @@ IMPL_LINK_NOARG(WeldToolbarPopup, FocusHdl, weld::Widget&, void)
     GrabFocus();
 }
 
-InterimToolbarPopup::InterimToolbarPopup(const css::uno::Reference<css::frame::XFrame>& rFrame, vcl::Window* pParent, WeldToolbarPopup* pPopup)
+ToolbarPopupContainer::ToolbarPopupContainer(weld::Widget* pParent)
+    : m_xBuilder(Application::CreateBuilder(pParent, "svx/ui/toolbarpopover.ui"))
+    , m_xTopLevel(m_xBuilder->weld_container("ToolbarPopover"))
+    , m_xContainer(m_xBuilder->weld_container("container"))
+{
+    m_xTopLevel->connect_focus_in(LINK(this, ToolbarPopupContainer, FocusHdl));
+}
+
+void ToolbarPopupContainer::setPopover(std::unique_ptr<WeldToolbarPopup> xPopup)
+{
+    m_xPopup = std::move(xPopup);
+    // move the WeldToolbarPopup contents into this toolbar so on-demand contents can appear inside a preexisting gtk popover
+    // because the arrow for the popover is only enabled if there's a popover set
+    m_xPopup->getTopLevel()->move(m_xPopup->getContainer(), m_xContainer.get());
+    m_xPopup->GrabFocus();
+}
+
+void ToolbarPopupContainer::unsetPopover()
+{
+    if (!m_xPopup)
+        return;
+    m_xContainer->move(m_xPopup->getContainer(), m_xPopup->getTopLevel());
+    m_xPopup.reset();
+}
+
+ToolbarPopupContainer::~ToolbarPopupContainer()
+{
+    unsetPopover();
+}
+
+IMPL_LINK_NOARG(ToolbarPopupContainer, FocusHdl, weld::Widget&, void)
+{
+    if (m_xPopup)
+        m_xPopup->GrabFocus();
+}
+
+InterimToolbarPopup::InterimToolbarPopup(const css::uno::Reference<css::frame::XFrame>& rFrame, vcl::Window* pParent,
+                                         std::unique_ptr<WeldToolbarPopup> xPopup)
     : ToolbarPopup(rFrame, pParent, "InterimDockParent", "svx/ui/interimdockparent.ui")
     , m_xBox(get<vcl::Window>("box"))
     , m_xBuilder(Application::CreateInterimBuilder(m_xBox.get(), "svx/ui/interimparent.ui"))
     , m_xContainer(m_xBuilder->weld_container("container"))
-    , m_pPopup(pPopup)
+    , m_xPopup(std::move(xPopup))
 {
     // move the WeldToolbarPopup contents into this interim toolbar so welded contents can appear as a dropdown in an unwelded toolbar
-    m_pPopup->getTopLevel()->move(m_pPopup->getContainer(), m_xContainer.get());
+    m_xPopup->getTopLevel()->move(m_xPopup->getContainer(), m_xContainer.get());
 }
 
 void InterimToolbarPopup::GetFocus()
 {
     ToolbarPopup::GetFocus();
-    m_pPopup->GrabFocus();
+    m_xPopup->GrabFocus();
 }
 
 void InterimToolbarPopup::dispose()
 {
     // move the contents back where it belongs
-    m_xContainer->move(m_pPopup->getContainer(), m_pPopup->getTopLevel());
+    m_xContainer->move(m_xPopup->getContainer(), m_xPopup->getTopLevel());
+    m_xPopup.reset();
     m_xContainer.reset();
     m_xBox.clear();
     ToolbarPopup::dispose();
diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx
index 7b1e3357424d..50135adbe453 100644
--- a/svtools/source/uno/popupwindowcontroller.cxx
+++ b/svtools/source/uno/popupwindowcontroller.cxx
@@ -177,7 +177,7 @@ sal_Bool SAL_CALL PopupWindowController::supportsService( const OUString& Servic
 void SAL_CALL PopupWindowController::dispose()
 {
     mxInterimPopover.clear();
-    mxPopover.reset();
+    mxPopoverContainer.reset();
     mxImpl.reset();
     svt::ToolboxController::dispose();
 }
@@ -207,8 +207,20 @@ void SAL_CALL PopupWindowController::statusChanged( const frame::FeatureStateEve
     }
 }
 
+std::unique_ptr<WeldToolbarPopup> PopupWindowController::weldPopupWindow()
+{
+    return nullptr;
+}
+
 Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow()
 {
+    if (m_pToolbar)
+    {
+        mxPopoverContainer->unsetPopover();
+        mxPopoverContainer->setPopover(weldPopupWindow());
+        return Reference<awt::XWindow>();
+    }
+
     VclPtr< ToolBox > pToolBox = dynamic_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ).get() );
     if( pToolBox )
     {
@@ -237,6 +249,19 @@ Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow()
     return Reference< awt::XWindow >();
 }
 
+void SAL_CALL PopupWindowController::click()
+{
+    if (m_pToolbar)
+    {
+        if (m_pToolbar->get_menu_item_active(m_aCommandURL.toUtf8()))
+            createPopupWindow();
+        else
+            mxPopoverContainer->unsetPopover();
+    }
+
+    svt::ToolboxController::click();
+}
+
 void PopupWindowController::EndPopupMode()
 {
     if (m_pToolbar)
diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk
index 070e52ade41f..f81460e52571 100644
--- a/svx/UIConfig_svx.mk
+++ b/svx/UIConfig_svx.mk
@@ -106,6 +106,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\
 	svx/uiconfig/ui/textcontrolchardialog \
 	svx/uiconfig/ui/textcontrolparadialog \
 	svx/uiconfig/ui/textunderlinecontrol \
+	svx/uiconfig/ui/toolbarpopover \
 	svx/uiconfig/ui/xmlsecstatmenu \
 	svx/uiconfig/ui/xformspage \
 	svx/uiconfig/ui/zoommenu \
diff --git a/svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx b/svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx
index 6a7b7b578222..93ced9fece15 100644
--- a/svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx
+++ b/svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx
@@ -94,7 +94,7 @@ ParaLineSpacingControl::ParaLineSpacingControl(SvxLineSpacingToolBoxControl* pCo
 
     SetFieldUnit(*mxLineDistAtMetricBox, eUnit);
 
-    SyncFromDocument();
+    Initialize();
 }
 
 void ParaLineSpacingControl::GrabFocus()
@@ -106,7 +106,7 @@ ParaLineSpacingControl::~ParaLineSpacingControl()
 {
 }
 
-void ParaLineSpacingControl::SyncFromDocument()
+void ParaLineSpacingControl::Initialize()
 {
     const SfxPoolItem* pItem(nullptr);
     SfxViewFrame* pCurrent = SfxViewFrame::Current();
diff --git a/svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx b/svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx
index 6d999159212f..3f5c12f8ca21 100644
--- a/svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx
+++ b/svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx
@@ -35,7 +35,7 @@ public:
     virtual ~ParaLineSpacingControl() override;
 
     /// Setup the widgets with values from the document.
-    void SyncFromDocument();
+    void Initialize();
 
     virtual void GrabFocus() override;
 
diff --git a/svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx b/svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx
index 90099ac75511..470e5eb7e3fd 100644
--- a/svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx
+++ b/svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx
@@ -37,24 +37,16 @@ void SvxLineSpacingToolBoxControl::initialize( const css::uno::Sequence< css::un
 {
     PopupWindowController::initialize(rArguments);
 
+    if (m_pToolbar)
+    {
+        mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
+        m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel());
+    }
+
     ToolBox* pToolBox = nullptr;
     sal_uInt16 nId = 0;
-    bool bVcl = getToolboxId(nId, &pToolBox);
-
-    weld::Widget* pParent;
-    if (pToolBox)
-        pParent = pToolBox->GetFrameWeld();
-    else
-        pParent = m_pToolbar;
-    mxPopover = std::make_unique<ParaLineSpacingControl>(this, pParent);
-
-    if (bVcl && pToolBox->GetItemCommand(nId) == m_aCommandURL)
+    if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL)
         pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId));
-    else if (m_pToolbar)
-    {
-        const OString aId(m_aCommandURL.toUtf8());
-        m_pToolbar->set_item_popover(aId, mxPopover->getTopLevel());
-    }
 }
 
 void SAL_CALL SvxLineSpacingToolBoxControl::execute(sal_Int16 /*KeyModifier*/)
@@ -72,11 +64,15 @@ void SAL_CALL SvxLineSpacingToolBoxControl::execute(sal_Int16 /*KeyModifier*/)
     }
 }
 
-VclPtr<vcl::Window> SvxLineSpacingToolBoxControl::createPopupWindow( vcl::Window* pParent )
+std::unique_ptr<WeldToolbarPopup> SvxLineSpacingToolBoxControl::weldPopupWindow()
 {
-    dynamic_cast<ParaLineSpacingControl&>(*mxPopover).SyncFromDocument();
+    return std::make_unique<ParaLineSpacingControl>(this, m_pToolbar);
+}
 
-    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, mxPopover.get());
+VclPtr<vcl::Window> SvxLineSpacingToolBoxControl::createPopupWindow( vcl::Window* pParent )
+{
+    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
+        std::make_unique<ParaLineSpacingControl>(this, pParent->GetFrameWeld()));
 
     mxInterimPopover->Show();
 
diff --git a/svx/source/tbxctrls/bulletsnumbering.cxx b/svx/source/tbxctrls/bulletsnumbering.cxx
index d33f790a5250..ba63a41b8838 100644
--- a/svx/source/tbxctrls/bulletsnumbering.cxx
+++ b/svx/source/tbxctrls/bulletsnumbering.cxx
@@ -53,6 +53,7 @@ class NumberingToolBoxControl : public svt::PopupWindowController
 public:
     explicit NumberingToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) override;
+    std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
 
     // XInitialization
     virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
@@ -185,9 +186,15 @@ NumberingToolBoxControl::NumberingToolBoxControl( const css::uno::Reference< css
 {
 }
 
+std::unique_ptr<WeldToolbarPopup> NumberingToolBoxControl::weldPopupWindow()
+{
+    return std::make_unique<NumberingPopup>(*this, m_pToolbar, mePageType);
+}
+
 VclPtr<vcl::Window> NumberingToolBoxControl::createPopupWindow( vcl::Window* pParent )
 {
-    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, mxPopover.get());
+    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
+        std::make_unique<NumberingPopup>(*this, pParent->GetFrameWeld(), mePageType));
 
     mxInterimPopover->Show();
 
@@ -203,24 +210,19 @@ void SAL_CALL NumberingToolBoxControl::initialize( const css::uno::Sequence< css
     else if ( m_aCommandURL == ".uno:SetOutline" )
         mePageType = NumberingPageType::OUTLINE;
 
-    ToolBoxItemBits nBits = ( mePageType == NumberingPageType::OUTLINE ) ? ToolBoxItemBits::DROPDOWNONLY : ToolBoxItemBits::DROPDOWN;
+    if (m_pToolbar)
+    {
+        mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
+        m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel());
+        return;
+    }
+
     ToolBox* pToolBox = nullptr;
     sal_uInt16 nId = 0;
-    bool bVcl = getToolboxId(nId, &pToolBox);
-
-    weld::Widget* pParent;
-    if (pToolBox)
-        pParent = pToolBox->GetFrameWeld();
-    else
-        pParent = m_pToolbar;
-    mxPopover = std::make_unique<NumberingPopup>(*this, pParent, mePageType);
-
-    if (bVcl)
-        pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | nBits );
-    else if (m_pToolbar)
+    if (getToolboxId(nId, &pToolBox))
     {
-        const OString aId(m_aCommandURL.toUtf8());
-        m_pToolbar->set_item_popover(aId, mxPopover->getTopLevel());
+        ToolBoxItemBits nBits = ( mePageType == NumberingPageType::OUTLINE ) ? ToolBoxItemBits::DROPDOWNONLY : ToolBoxItemBits::DROPDOWN;
+        pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | nBits );
     }
 }
 
diff --git a/svx/source/tbxctrls/tbcontrl.cxx b/svx/source/tbxctrls/tbcontrl.cxx
index 322bf970b54e..2f11f9f34aa0 100644
--- a/svx/source/tbxctrls/tbcontrl.cxx
+++ b/svx/source/tbxctrls/tbcontrl.cxx
@@ -3378,32 +3378,12 @@ void SvxColorToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>
     auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(getCommandURL(), getModuleName());
     OUString aCommandLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
 
+    OString aId(m_aCommandURL.toUtf8());
+
     if (m_pToolbar)
     {
-        EnsurePaletteManager();
-
-        const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow();
-        weld::Window* pParentFrame = Application::GetFrameWeld(xParent);
-
-        const OString aId(m_aCommandURL.toUtf8());
-
-        auto xPopover = std::make_unique<ColorWindow>(
-                            m_aCommandURL,
-                            m_xPaletteManager,
-                            m_aColorStatus,
-                            m_nSlotId,
-                            m_xFrame,
-                            pParentFrame,
-                            MenuOrToolMenuButton(m_pToolbar, aId),
-                            m_aColorSelectFunction);
-
-        if ( m_bSplitButton )
-            xPopover->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) );
-
-        mxPopover = std::move(xPopover);
-
-        m_pToolbar->set_item_popover(aId, mxPopover->getTopLevel());
-
+        mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
+        m_pToolbar->set_item_popover(aId, mxPopoverContainer->getTopLevel());
         m_xBtnUpdater.reset(new svx::ToolboxButtonColorUpdater(m_nSlotId, aId, m_pToolbar, !m_bSplitButton, aCommandLabel, m_xFrame));
         return;
     }
@@ -3460,6 +3440,31 @@ void SvxColorToolBoxControl::setColorSelectFunction(const ColorSelectFunction& a
         m_xPaletteManager->SetColorSelectFunction(aColorSelectFunction);
 }
 
+std::unique_ptr<WeldToolbarPopup> SvxColorToolBoxControl::weldPopupWindow()
+{
+    EnsurePaletteManager();
+
+    const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow();
+    weld::Window* pParentFrame = Application::GetFrameWeld(xParent);
+
+    const OString aId(m_aCommandURL.toUtf8());
+
+    auto xPopover = std::make_unique<ColorWindow>(
+                        m_aCommandURL,
+                        m_xPaletteManager,
+                        m_aColorStatus,
+                        m_nSlotId,
+                        m_xFrame,
+                        pParentFrame,
+                        MenuOrToolMenuButton(m_pToolbar, aId),
+                        m_aColorSelectFunction);
+
+    if ( m_bSplitButton )
+        xPopover->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) );
+
+    return xPopover;
+}
+
 VclPtr<vcl::Window> SvxColorToolBoxControl::createPopupWindow( vcl::Window* pParent )
 {
     EnsurePaletteManager();
@@ -3819,29 +3824,28 @@ void SvxCurrencyToolBoxControl::initialize( const css::uno::Sequence< css::uno::
 {
     PopupWindowController::initialize(rArguments);
 
+    if (m_pToolbar)
+    {
+        mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
+        m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel());
+        return;
+    }
+
     ToolBox* pToolBox = nullptr;
     sal_uInt16 nId = 0;
-    bool bVcl = getToolboxId(nId, &pToolBox);
-
-    weld::Widget* pParent;
-    if (pToolBox)
-        pParent = pToolBox->GetFrameWeld();
-    else
-        pParent = m_pToolbar;
-    mxPopover = std::make_unique<SvxCurrencyList_Impl>(this, pParent, m_aFormatString, m_eLanguage);
-
-    if (bVcl && pToolBox->GetItemCommand(nId) == m_aCommandURL)
+    if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL)
         pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId));
-    else if (m_pToolbar)
-    {
-        const OString aId(m_aCommandURL.toUtf8());
-        m_pToolbar->set_item_popover(aId, mxPopover->getTopLevel());
-    }
+}
+
+std::unique_ptr<WeldToolbarPopup> SvxCurrencyToolBoxControl::weldPopupWindow()
+{
+    return std::make_unique<SvxCurrencyList_Impl>(this, m_pToolbar, m_aFormatString, m_eLanguage);
 }
 
 VclPtr<vcl::Window> SvxCurrencyToolBoxControl::createPopupWindow( vcl::Window* pParent )
 {
-    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, mxPopover.get());
+    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
+        std::make_unique<SvxCurrencyList_Impl>(this, pParent->GetFrameWeld(), m_aFormatString, m_eLanguage));
 
     mxInterimPopover->Show();
 
diff --git a/svx/uiconfig/ui/colorwindow.ui b/svx/uiconfig/ui/colorwindow.ui
index 853ce6831900..23f53b866543 100644
--- a/svx/uiconfig/ui/colorwindow.ui
+++ b/svx/uiconfig/ui/colorwindow.ui
@@ -25,7 +25,7 @@
     <property name="no_show_all">True</property>
     <property name="border_width">4</property>
     <child>
-      <object class="GtkBox" id="box1">
+      <object class="GtkBox" id="container">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
diff --git a/svx/uiconfig/ui/toolbarpopover.ui b/svx/uiconfig/ui/toolbarpopover.ui
new file mode 100644
index 000000000000..828bc6e9dc1c
--- /dev/null
+++ b/svx/uiconfig/ui/toolbarpopover.ui
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="svx">
+  <requires lib="gtk+" version="3.18"/>
+  <object class="GtkPopover" id="ToolbarPopover">
+    <property name="can_focus">False</property>
+    <property name="no_show_all">True</property>
+    <property name="border_width">4</property>
+    <child>
+      <object class="GtkBox" id="container">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 3ef767cb13fe..0dd8825754dc 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -950,8 +950,11 @@ private:
     std::map<sal_uInt16, VclPtr<vcl::Window>> m_aFloats;
     std::map<sal_uInt16, VclPtr<PopupMenu>> m_aMenus;
 
+    OString m_sStartShowIdent;
+
     DECL_LINK(ClickHdl, ToolBox*, void);
     DECL_LINK(DropdownClick, ToolBox*, void);
+    DECL_LINK(MenuToggleListener, VclWindowEvent&, void);
 
 public:
     SalInstanceToolbar(ToolBox* pToolBox, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
@@ -1024,6 +1027,9 @@ public:
         sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
         assert (m_xToolBox->GetItemBits(nItemId) & ToolBoxItemBits::DROPDOWN);
 
+        if (rIdent == m_sStartShowIdent)
+            return true;
+
         auto aFloat = m_aFloats.find(nItemId);
         if (aFloat != m_aFloats.end())
         {
@@ -1045,9 +1051,17 @@ public:
 
         vcl::Window* pFloat = pPopoverWidget ? pPopoverWidget->getWidget() : nullptr;
         if (pFloat)
+        {
+            pFloat->AddEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
             pFloat->EnableDocking();
+        }
 
         sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
+        auto xOldFloat = m_aFloats[nId];
+        if (xOldFloat)
+        {
+            xOldFloat->RemoveEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
+        }
         m_aFloats[nId] = pFloat;
         m_aMenus[nId] = nullptr;
     }
@@ -1161,9 +1175,26 @@ IMPL_LINK_NOARG(SalInstanceToolbar, DropdownClick, ToolBox*, void)
 {
     sal_uInt16 nItemId = m_xToolBox->GetCurItemId();
 
-    OString sIdent = m_xToolBox->GetItemCommand(nItemId).toUtf8();
-    signal_show_menu(sIdent);
-    set_menu_item_active(sIdent, true);
+    m_sStartShowIdent = m_xToolBox->GetItemCommand(nItemId).toUtf8();
+    signal_toggle_menu(m_sStartShowIdent);
+    set_menu_item_active(m_sStartShowIdent, true);
+    m_sStartShowIdent.clear();
+}
+
+IMPL_LINK(SalInstanceToolbar, MenuToggleListener, VclWindowEvent&, rEvent, void)
+{
+    if (rEvent.GetId() == VclEventId::WindowEndPopupMode)
+    {
+        for (auto& rFloat : m_aFloats)
+        {
+            if (rEvent.GetWindow() == rFloat.second)
+            {
+                sal_uInt16 nItemId = rFloat.first;
+                signal_toggle_menu(m_xToolBox->GetItemCommand(nItemId).toUtf8());
+                break;
+            }
+        }
+    }
 }
 
 namespace {
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index bc53e4cf3cce..d52fb782df6a 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -7118,7 +7118,7 @@ private:
         if (pMenuButton)
         {
             m_aMenuButtonMap[id] = std::make_unique<GtkInstanceMenuButton>(pMenuButton, m_pBuilder, false);
-            g_signal_connect(pToolItem, "show-menu", G_CALLBACK(signalItemShowMenu), this);
+            g_signal_connect(pMenuButton, "toggled", G_CALLBACK(signalItemToggled), this);
         }
         g_signal_connect(pToolItem, "clicked", G_CALLBACK(signalItemClicked), this);
     }
@@ -7136,17 +7136,23 @@ private:
         signal_clicked(OString(pStr, pStr ? strlen(pStr) : 0));
     }
 
-    static void signalItemShowMenu(GtkMenuToolButton* pItem, gpointer widget)
+    static void signalItemToggled(GtkToggleButton* pItem, gpointer widget)
     {
         GtkInstanceToolbar* pThis = static_cast<GtkInstanceToolbar*>(widget);
         SolarMutexGuard aGuard;
-        pThis->signal_item_show_menu(pItem);
+        pThis->signal_item_toggled(pItem);
     }
 
-    void signal_item_show_menu(GtkMenuToolButton* pItem)
+    void signal_item_toggled(GtkToggleButton* pItem)
     {
-        const gchar* pStr = gtk_buildable_get_name(GTK_BUILDABLE(pItem));
-        signal_show_menu(OString(pStr, pStr ? strlen(pStr) : 0));
+        for (auto& a : m_aMenuButtonMap)
+        {
+            if (a.second->getWidget() == GTK_WIDGET(pItem))
+            {
+                signal_toggle_menu(a.first);
+                break;
+            }
+        }
     }
 
     static void set_item_image(GtkToolButton* pItem, const css::uno::Reference<css::graphic::XGraphic>& rIcon)
@@ -7189,7 +7195,6 @@ public:
         for (auto& a : m_aMap)
         {
             g_signal_handlers_block_by_func(a.second, reinterpret_cast<void*>(signalItemClicked), this);
-            g_signal_handlers_block_by_func(a.second, reinterpret_cast<void*>(signalItemShowMenu), this);
         }
     }
 
@@ -7197,7 +7202,6 @@ public:
     {
         for (auto& a : m_aMap)
         {
-            g_signal_handlers_unblock_by_func(a.second, reinterpret_cast<void*>(signalItemShowMenu), this);
             g_signal_handlers_unblock_by_func(a.second, reinterpret_cast<void*>(signalItemClicked), this);
         }
     }


More information about the Libreoffice-commits mailing list