compilerplugins/clang/badstatics.cxx | 1 vcl/inc/jsdialog/jsdialogbuilder.hxx | 9 +++++ vcl/jsdialog/jsdialogbuilder.cxx | 56 +++++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-)
New commits: commit 4ed7f5360016153ce022a2fe460791f636ba4ec8 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: Fri May 20 17:04:10 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> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134675 diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index 75eee2606769..240410faeb80 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 7ee18baef987..44747b8d3418 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -305,6 +305,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, VclPtr<vcl::Window> pWidget); + static void ForgetPopup(const std::string& nWindowId); + static vcl::Window* FindPopup(const std::string& nWindowId); + private: const std::string& GetTypeOfJSON() const; VclPtr<vcl::Window>& GetContentWindow(); @@ -701,6 +706,8 @@ public: class JSPopover : public JSWidget<SalInstancePopover, DockingWindow> { + vcl::LOKWindowId mnWindowId; + public: JSPopover(JSDialogSender* pSender, DockingWindow* pPopover, SalInstanceBuilder* pBuilder, bool bTakeOwnership); @@ -708,6 +715,8 @@ public: virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect, weld::Placement ePlace = weld::Placement::Under) 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 e46f02fbebfc..eba186082659 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, vcl::Window*>& GetLOKPopupsMap() +{ + // Map to remember the LOKWindowId <-> vcl popup binding. + static std::map<std::string, vcl::Window*> s_aLOKPopupsMap; + + return s_aLOKPopupsMap; +} + namespace { void response_help(vcl::Window* pWindow) @@ -673,6 +681,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() @@ -764,6 +774,28 @@ void JSInstanceBuilder::RemoveWindowWidget(const std::string& nWindowId) } } +void JSInstanceBuilder::RememberPopup(const std::string& nWindowId, VclPtr<vcl::Window> pWidget) +{ + GetLOKPopupsMap()[nWindowId] = pWidget; +} + +void JSInstanceBuilder::ForgetPopup(const std::string& nWindowId) +{ + auto it = GetLOKPopupsMap().find(nWindowId); + if (it != GetLOKPopupsMap().end()) + GetLOKPopupsMap().erase(it); +} + +vcl::Window* JSInstanceBuilder::FindPopup(const std::string& nWindowId) +{ + const auto it = GetLOKPopupsMap().find(nWindowId); + + if (it != GetLOKPopupsMap().end()) + return it->second; + + return nullptr; +} + const std::string& JSInstanceBuilder::GetTypeOfJSON() const { return m_sTypeOfJSON; } VclPtr<vcl::Window>& JSInstanceBuilder::GetContentWindow() @@ -1050,8 +1082,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"); @@ -1065,6 +1098,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), pDockingWindow); + InsertWindowToMap(getMapIdFromWindowId()); initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); } @@ -1466,10 +1503,16 @@ void JSToolbar::set_menu_item_active(const OString& rIdent, bool bActive) if (pPopupRoot) { if (bActive) + { + JSInstanceBuilder::RememberPopup(std::to_string(pPopupRoot->GetLOKWindowId()), pFloat); sendPopup(pPopupRoot, m_xToolBox->get_id(), OStringToOUString(rIdent, RTL_TEXTENCODING_ASCII_US)); + } else if (bWasActive) + { + JSInstanceBuilder::ForgetPopup(std::to_string(pPopupRoot->GetLOKWindowId())); sendClosePopup(pPopupRoot->GetLOKWindowId()); + } } } @@ -1757,8 +1800,17 @@ void JSPopover::popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRe void JSPopover::popdown() { + vcl::Window* pPopup = JSInstanceBuilder::FindPopup(std::to_string(mnWindowId)); + + if (pPopup) + { + sendClosePopup(mnWindowId); + vcl::Window::GetDockingManager()->EndPopupMode(pPopup); + } + if (getWidget() && getWidget()->GetChild(0)) sendClosePopup(getWidget()->GetChild(0)->GetLOKWindowId()); + SalInstancePopover::popdown(); }