compilerplugins/clang/badstatics.cxx |    1 
 include/vcl/jsdialog/executor.hxx    |    2 -
 vcl/inc/jsdialog/jsdialogbuilder.hxx |   10 +++++
 vcl/jsdialog/jsdialogbuilder.cxx     |   59 +++++++++++++++++++++++++++++++++--
 4 files changed, 69 insertions(+), 3 deletions(-)

New commits:
commit 11dd8edeafb6ed237698149dd0f679851fbbce0b
Author:     Szymon Kłos <eszka...@gmail.com>
AuthorDate: Wed May 18 23:28:30 2022 +0200
Commit:     Szymon Kłos <szymon.k...@collabora.com>
CommitDate: Thu May 19 09:29:52 2022 +0200

    jsdialog: introduce popup management
    
    Popup windows are managed by vcl (some moving between parents
    happens on show/hide popup).
    
    We need to access correct popup window to correctly close
    popup in LOK. So remember popup instances.
    
    Change-Id: I9e1ba18ded5a1bf675f95bd7178043eebd9bbd5a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134576
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Mert Tumer <mert.tu...@collabora.com>

diff --git a/compilerplugins/clang/badstatics.cxx 
b/compilerplugins/clang/badstatics.cxx
index 3f4d6cddecd3..8219108ce9be 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -208,6 +208,7 @@ public:
                     .Class("ScDocument").GlobalNamespace()) // not owning
                 || name == "s_aLOKWindowsMap" // LOK only, guarded by assert, 
and LOK never tries to perform a VCL cleanup
                 || name == "s_aLOKWeldBuildersMap" // LOK only, similar case 
as above
+                || name == "s_aLOKPopupsMap" // LOK only, similar case as above
                 || name == "m_pNotebookBarWeldedWrapper" // LOK only, warning 
about map's key, no VCL cleanup performed
                 || name == "gStaticManager" // vcl/source/graphic/Manager.cxx 
- stores non-owning pointers
                 || name == "aThreadedInterpreterPool"    // 
ScInterpreterContext(Pool), not owning
diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx 
b/vcl/inc/jsdialog/jsdialogbuilder.hxx
index 968d5e97504d..ffc7e19ae872 100644
--- a/vcl/inc/jsdialog/jsdialogbuilder.hxx
+++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx
@@ -40,6 +40,7 @@ class SvTabListBox;
 class IconView;
 
 typedef std::map<OString, weld::Widget*> WidgetMap;
+typedef std::map<OString, vcl::Window*> PopupMap;
 typedef std::unordered_map<std::string, OUString> ActionDataMap;
 
 namespace jsdialog
@@ -296,6 +297,11 @@ public:
                                weld::Widget* pWidget);
     static void RemoveWindowWidget(const std::string& nWindowId);
 
+    // we need to remember original popup window to close it properly (its 
handled by vcl)
+    static void RememberPopup(const std::string& nWindowId, const OString& id,
+                              VclPtr<vcl::Window> pWidget);
+    static vcl::Window* FindPopup(const std::string& nWindowId, const OString& 
id);
+
 private:
     const std::string& GetTypeOfJSON();
     VclPtr<vcl::Window>& GetContentWindow();
@@ -690,12 +696,16 @@ public:
 
 class JSPopover : public JSWidget<SalInstancePopover, DockingWindow>
 {
+    vcl::LOKWindowId mnWindowId;
+
 public:
     JSPopover(JSDialogSender* pSender, DockingWindow* pPopover, 
SalInstanceBuilder* pBuilder,
               bool bTakeOwnership);
 
     virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& 
rRect) override;
     virtual void popdown() override;
+
+    void set_window_id(vcl::LOKWindowId nWindowId) { mnWindowId = nWindowId; }
 };
 
 class JSBox : public JSWidget<SalInstanceBox, VclBox>
diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx
index f99367d1f4b8..ff543ca60be8 100644
--- a/vcl/jsdialog/jsdialogbuilder.cxx
+++ b/vcl/jsdialog/jsdialogbuilder.cxx
@@ -27,6 +27,14 @@
 #include <cppuhelper/supportsservice.hxx>
 #include <utility>
 
+static std::map<std::string, PopupMap>& GetLOKPopupsMap()
+{
+    // Map to remember the LOKWindowId <-> vcl popup binding.
+    static std::map<std::string, PopupMap> s_aLOKPopupsMap;
+
+    return s_aLOKPopupsMap;
+}
+
 namespace
 {
 void response_help(vcl::Window* pWindow)
@@ -677,6 +685,8 @@ JSInstanceBuilder::~JSInstanceBuilder()
                           [it](std::string& sId) { 
it->second.erase(sId.c_str()); });
         }
     }
+
+    GetLOKPopupsMap().erase(std::to_string(m_nWindowId));
 }
 
 std::map<std::string, WidgetMap>& JSInstanceBuilder::GetLOKWeldWidgetsMap()
@@ -768,6 +778,36 @@ void JSInstanceBuilder::RemoveWindowWidget(const 
std::string& nWindowId)
     }
 }
 
+void JSInstanceBuilder::RememberPopup(const std::string& nWindowId, const 
OString& id,
+                                      VclPtr<vcl::Window> pWidget)
+{
+    PopupMap map;
+    auto it = GetLOKPopupsMap().find(nWindowId);
+    if (it == GetLOKPopupsMap().end())
+        GetLOKPopupsMap().insert(std::map<std::string, 
PopupMap>::value_type(nWindowId, map));
+
+    it = GetLOKPopupsMap().find(nWindowId);
+    if (it != GetLOKPopupsMap().end())
+    {
+        it->second.erase(id);
+        it->second.insert(PopupMap::value_type(id, pWidget));
+    }
+}
+
+vcl::Window* JSInstanceBuilder::FindPopup(const std::string& nWindowId, const 
OString& id)
+{
+    const auto it = GetLOKPopupsMap().find(nWindowId);
+
+    if (it != GetLOKPopupsMap().end())
+    {
+        auto widgetIt = it->second.find(id);
+        if (widgetIt != it->second.end())
+            return widgetIt->second;
+    }
+
+    return nullptr;
+}
+
 const std::string& JSInstanceBuilder::GetTypeOfJSON() { return m_sTypeOfJSON; }
 
 VclPtr<vcl::Window>& JSInstanceBuilder::GetContentWindow()
@@ -1055,8 +1095,9 @@ std::unique_ptr<weld::MenuButton> 
JSInstanceBuilder::weld_menu_button(const OStr
 std::unique_ptr<weld::Popover> JSInstanceBuilder::weld_popover(const OString& 
id)
 {
     DockingWindow* pDockingWindow = m_xBuilder->get<DockingWindow>(id);
-    std::unique_ptr<weld::Popover> pWeldWidget(
-        pDockingWindow ? new JSPopover(this, pDockingWindow, this, false) : 
nullptr);
+    JSPopover* pPopover
+        = pDockingWindow ? new JSPopover(this, pDockingWindow, this, false) : 
nullptr;
+    std::unique_ptr<weld::Popover> pWeldWidget(pPopover);
     if (pDockingWindow)
     {
         assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
@@ -1070,6 +1111,10 @@ std::unique_ptr<weld::Popover> 
JSInstanceBuilder::weld_popover(const OString& id
             m_aParentDialog = pPopupRoot;
             m_aWindowToRelease = pPopupRoot;
             m_nWindowId = m_aParentDialog->GetLOKWindowId();
+
+            pPopover->set_window_id(m_nWindowId);
+            JSInstanceBuilder::RememberPopup(std::to_string(m_nWindowId), id, 
pDockingWindow);
+
             InsertWindowToMap(getMapIdFromWindowId());
             initializeSender(GetNotifierWindow(), GetContentWindow(), 
GetTypeOfJSON());
         }
@@ -1761,8 +1806,18 @@ void JSPopover::popup_at_rect(weld::Widget* pParent, 
const tools::Rectangle& rRe
 
 void JSPopover::popdown()
 {
+    vcl::Window* pPopup
+        = JSInstanceBuilder::FindPopup(std::to_string(mnWindowId), 
get_buildable_name());
+
+    if (pPopup)
+    {
+        sendClosePopup(mnWindowId);
+        vcl::Window::GetDockingManager()->EndPopupMode(pPopup);
+    }
+
     if (getWidget() && getWidget()->GetChild(0))
         sendClosePopup(getWidget()->GetChild(0)->GetLOKWindowId());
+
     SalInstancePopover::popdown();
 }
 
commit 1e9c8a6336146dceeeb81e682a6415f3527517ac
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Wed Apr 6 09:52:34 2022 +0200
Commit:     Szymon Kłos <szymon.k...@collabora.com>
CommitDate: Thu May 19 09:29:40 2022 +0200

    jsdialog: close popup correctly
    
    call popdown so we will mark popup as closed in DockingManager
    this fixes crash when trying to open autofilter popup second time
    
    Change-Id: I9f2db6fe284d9b9770c20dea4b8a4054524a998b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132619
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Mert Tumer <mert.tu...@collabora.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134575

diff --git a/include/vcl/jsdialog/executor.hxx 
b/include/vcl/jsdialog/executor.hxx
index 39c8c77f3a24..3bf7f91e1a69 100644
--- a/include/vcl/jsdialog/executor.hxx
+++ b/include/vcl/jsdialog/executor.hxx
@@ -55,7 +55,7 @@ public:
         rSpinButton.signal_value_changed();
     }
 
-    static void trigger_closed(weld::Popover& rPopover) { 
rPopover.signal_closed(); }
+    static void trigger_closed(weld::Popover& rPopover) { rPopover.popdown(); }
 };
 
 namespace jsdialog

Reply via email to