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