summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzymon Kłos <eszkadev@gmail.com>2022-05-18 23:28:30 +0200
committerSzymon Kłos <szymon.klos@collabora.com>2022-05-19 09:29:52 +0200
commit11dd8edeafb6ed237698149dd0f679851fbbce0b (patch)
tree566c0d3343d8f4aaddef7cd5c1b438a2bcba21b6
parent1e9c8a6336146dceeeb81e682a6415f3527517ac (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.cxx1
-rw-r--r--vcl/inc/jsdialog/jsdialogbuilder.hxx10
-rw-r--r--vcl/jsdialog/jsdialogbuilder.cxx59
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();
}