diff options
author | Szymon Kłos <eszkadev@gmail.com> | 2022-05-18 23:28:30 +0200 |
---|---|---|
committer | Szymon Kłos <szymon.klos@collabora.com> | 2022-05-19 09:29:52 +0200 |
commit | 11dd8edeafb6ed237698149dd0f679851fbbce0b (patch) | |
tree | 566c0d3343d8f4aaddef7cd5c1b438a2bcba21b6 | |
parent | 1e9c8a6336146dceeeb81e682a6415f3527517ac (diff) |
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 <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Mert Tumer <mert.tumer@collabora.com>
-rw-r--r-- | compilerplugins/clang/badstatics.cxx | 1 | ||||
-rw-r--r-- | vcl/inc/jsdialog/jsdialogbuilder.hxx | 10 | ||||
-rw-r--r-- | vcl/jsdialog/jsdialogbuilder.cxx | 59 |
3 files changed, 68 insertions, 2 deletions
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(); } |