include/vcl/weld.hxx                            |   16 ++
 sw/source/core/crsr/DateFormFieldButton.cxx     |  116 ++++-------------
 sw/source/core/crsr/DropDownFormFieldButton.cxx |  163 +++++++-----------------
 sw/source/core/crsr/FormFieldButton.cxx         |   37 +++--
 sw/source/core/inc/DateFormFieldButton.hxx      |   15 +-
 sw/source/core/inc/DropDownFormFieldButton.hxx  |   16 +-
 sw/source/core/inc/FormFieldButton.hxx          |   10 -
 sw/uiconfig/swriter/ui/calendar.ui              |   38 +++--
 sw/uiconfig/swriter/ui/formdropdown.ui          |   72 +++++-----
 vcl/inc/salvtables.hxx                          |    2 
 vcl/source/app/salvtables.cxx                   |   62 +++++++++
 vcl/unx/gtk3/gtk3gtkinst.cxx                    |  120 ++++++++++++++---
 12 files changed, 369 insertions(+), 298 deletions(-)

New commits:
commit a5a71c7bb58a16a64c586c3ea142e0dd88cf7104
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Feb 25 17:03:31 2021 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Fri Feb 26 20:57:31 2021 +0100

    drop intermediate vcl container for these welded floating toplevels
    
    Change-Id: I4a528485de62a0e0acabd41abf6872e2f0e1710e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111567
    Tested-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 14c7e77b33ea..eda93398b8d6 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -2264,6 +2264,21 @@ public:
     virtual ~Menu() {}
 };
 
+class VCL_DLLPUBLIC Popover : virtual public Container
+{
+private:
+    Link<weld::Popover&, void> m_aCloseHdl;
+
+protected:
+    void signal_closed() { m_aCloseHdl.Call(*this); }
+
+public:
+    virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& 
rRect) = 0;
+    virtual void popdown() = 0;
+
+    void connect_closed(const Link<weld::Popover&, void>& rLink) { m_aCloseHdl 
= rLink; }
+};
+
 class VCL_DLLPUBLIC Toolbar : virtual public Widget
 {
 protected:
@@ -2383,6 +2398,7 @@ public:
                                                                 const OString& 
treeviewid)
         = 0;
     virtual std::unique_ptr<Menu> weld_menu(const OString& id) = 0;
+    virtual std::unique_ptr<Popover> weld_popover(const OString& id) = 0;
     virtual std::unique_ptr<Toolbar> weld_toolbar(const OString& id) = 0;
     virtual std::unique_ptr<SizeGroup> create_size_group() = 0;
     /* return a Dialog suitable to take a screenshot of containing the 
contents of the .ui file.
diff --git a/sw/source/core/crsr/DateFormFieldButton.cxx 
b/sw/source/core/crsr/DateFormFieldButton.cxx
index 2d4b66815daf..5a1bb75f7733 100644
--- a/sw/source/core/crsr/DateFormFieldButton.cxx
+++ b/sw/source/core/crsr/DateFormFieldButton.cxx
@@ -10,113 +10,55 @@
 #include <DateFormFieldButton.hxx>
 #include <edtwin.hxx>
 #include <bookmrk.hxx>
-#include <vcl/floatwin.hxx>
-#include <vcl/InterimItemWindow.hxx>
 #include <tools/date.hxx>
 #include <svl/zforlist.hxx>
+#include <vcl/svapp.hxx>
 
-namespace
+IMPL_LINK(DateFormFieldButton, ImplSelectHdl, weld::Calendar&, rCalendar, void)
 {
-class SwCalendarBox final : public InterimItemWindow
-{
-private:
-    std::unique_ptr<weld::Calendar> m_xCalendar;
-
-public:
-    SwCalendarBox(vcl::Window* pParent)
-        : InterimItemWindow(pParent, "modules/swriter/ui/calendar.ui", 
"Calendar")
-        , m_xCalendar(m_xBuilder->weld_calendar("date"))
-    {
-    }
-    weld::Calendar& get_widget() { return *m_xCalendar; }
-    virtual ~SwCalendarBox() override { disposeOnce(); }
-    virtual void dispose() override
-    {
-        m_xCalendar.reset();
-        InterimItemWindow::dispose();
-    }
-};
-
-class SwDatePickerDialog : public FloatingWindow
-{
-private:
-    VclPtr<SwCalendarBox> m_xCalendar;
-    sw::mark::DateFieldmark* m_pFieldmark;
-    SvNumberFormatter* m_pNumberFormatter;
-
-    DECL_LINK(ImplSelectHdl, weld::Calendar&, void);
-
-public:
-    SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark,
-                       SvNumberFormatter* pNumberFormatter);
-    virtual ~SwDatePickerDialog() override;
-    virtual void dispose() override;
-};
-}
-
-SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, 
sw::mark::DateFieldmark* pFieldmark,
-                                       SvNumberFormatter* pNumberFormatter)
-    : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW)
-    , m_xCalendar(VclPtr<SwCalendarBox>::Create(this))
-    , m_pFieldmark(pFieldmark)
-    , m_pNumberFormatter(pNumberFormatter)
-{
-    weld::Calendar& rCalendar = m_xCalendar->get_widget();
-
-    if (m_pFieldmark != nullptr)
-    {
-        std::pair<bool, double> aResult = m_pFieldmark->GetCurrentDate();
-        if (aResult.first)
-        {
-            const Date& rNullDate = m_pNumberFormatter->GetNullDate();
-            rCalendar.set_date(rNullDate + sal_Int32(aResult.second));
-        }
-    }
-
-    Size lbSize(rCalendar.get_preferred_size());
-
-    m_xCalendar->SetSizePixel(lbSize);
-    rCalendar.connect_activated(LINK(this, SwDatePickerDialog, ImplSelectHdl));
-    m_xCalendar->Show();
-
-    rCalendar.grab_focus();
-
-    SetSizePixel(lbSize);
-}
-
-SwDatePickerDialog::~SwDatePickerDialog() { disposeOnce(); }
-
-void SwDatePickerDialog::dispose()
-{
-    m_xCalendar.disposeAndClear();
-    FloatingWindow::dispose();
-}
-
-IMPL_LINK(SwDatePickerDialog, ImplSelectHdl, weld::Calendar&, rCalendar, void)
-{
-    if (m_pFieldmark != nullptr)
+    if (m_pDateFieldmark)
     {
         const Date& rNullDate = m_pNumberFormatter->GetNullDate();
         double dDate = rCalendar.get_date() - rNullDate;
-        m_pFieldmark->SetCurrentDate(dDate);
+        m_pDateFieldmark->SetCurrentDate(dDate);
     }
-    EndPopupMode();
+    m_xFieldPopup->popdown();
 }
 
 DateFormFieldButton::DateFormFieldButton(SwEditWin* pEditWin, 
sw::mark::DateFieldmark& rFieldmark,
                                          SvNumberFormatter* pNumberFormatter)
     : FormFieldButton(pEditWin, rFieldmark)
     , m_pNumberFormatter(pNumberFormatter)
+    , m_pDateFieldmark(dynamic_cast<sw::mark::DateFieldmark*>(&m_rFieldmark))
 {
 }
 
 DateFormFieldButton::~DateFormFieldButton() { disposeOnce(); }
 
-void DateFormFieldButton::InitPopup()
+void DateFormFieldButton::LaunchPopup()
+{
+    m_xFieldPopupBuilder.reset(
+        Application::CreateBuilder(GetFrameWeld(), 
"modules/swriter/ui/calendar.ui"));
+    m_xFieldPopup = m_xFieldPopupBuilder->weld_popover("Calendar");
+    m_xCalendar = m_xFieldPopupBuilder->weld_calendar("date");
+    if (m_pDateFieldmark)
+    {
+        std::pair<bool, double> aResult = m_pDateFieldmark->GetCurrentDate();
+        if (aResult.first)
+        {
+            const Date& rNullDate = m_pNumberFormatter->GetNullDate();
+            m_xCalendar->set_date(rNullDate + sal_Int32(aResult.second));
+        }
+    }
+    m_xCalendar->connect_activated(LINK(this, DateFormFieldButton, 
ImplSelectHdl));
+    FormFieldButton::LaunchPopup();
+    m_xCalendar->grab_focus();
+}
+
+void DateFormFieldButton::DestroyPopup()
 {
-    sw::mark::DateFieldmark* pDateFieldmark = 
dynamic_cast<sw::mark::DateFieldmark*>(&m_rFieldmark);
-    m_pFieldPopup = 
VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()),
-                                                       pDateFieldmark, 
m_pNumberFormatter);
+    m_xCalendar.reset();
+    FormFieldButton::DestroyPopup();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx 
b/sw/source/core/crsr/DropDownFormFieldButton.cxx
index 5a876f907f96..4dd968e7ee62 100644
--- a/sw/source/core/crsr/DropDownFormFieldButton.cxx
+++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx
@@ -10,9 +10,6 @@
 #include <DropDownFormFieldButton.hxx>
 #include <edtwin.hxx>
 #include <bookmrk.hxx>
-#include <vcl/event.hxx>
-#include <vcl/floatwin.hxx>
-#include <vcl/InterimItemWindow.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/svapp.hxx>
 #include <xmloff/odffields.hxx>
@@ -21,146 +18,76 @@
 #include <docsh.hxx>
 #include <strings.hrc>
 
-namespace
-{
-class SwFieldListBox final : public InterimItemWindow
-{
-private:
-    std::unique_ptr<weld::TreeView> m_xTreeView;
-
-public:
-    SwFieldListBox(vcl::Window* pParent)
-        : InterimItemWindow(pParent, "modules/swriter/ui/formdropdown.ui", 
"FormDropDown")
-        , m_xTreeView(m_xBuilder->weld_tree_view("list"))
-    {
-    }
-    weld::TreeView& get_widget() { return *m_xTreeView; }
-    virtual ~SwFieldListBox() override { disposeOnce(); }
-    virtual void dispose() override
-    {
-        m_xTreeView.reset();
-        InterimItemWindow::dispose();
-    }
-};
-
 /**
  * Popup dialog for drop-down form field showing the list items of the field.
  * The user can select the item using this popup while filling in a form.
  */
-class SwFieldDialog : public FloatingWindow
-{
-private:
-    VclPtr<SwFieldListBox> m_xListBox;
-    sw::mark::IFieldmark* m_pFieldmark;
-
-    DECL_LINK(MyListBoxHandler, weld::TreeView&, bool);
-    DECL_STATIC_LINK(SwFieldDialog, KeyInputHdl, const KeyEvent&, bool);
-
-public:
-    SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, 
tools::Long nMinListWidth);
-    virtual ~SwFieldDialog() override;
-    virtual void dispose() override;
-};
-}
 
-SwFieldDialog::SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM,
-                             tools::Long nMinListWidth)
-    : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW)
-    , m_xListBox(VclPtr<SwFieldListBox>::Create(this))
-    , m_pFieldmark(fieldBM)
+void DropDownFormFieldButton::InitDropdown()
 {
-    weld::TreeView& rTreeView = m_xListBox->get_widget();
+    const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
m_rFieldmark.GetParameters();
+
+    sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries
+        = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
+    css::uno::Sequence<OUString> vListEntries;
+    if (pListEntries != pParameters->end())
+    {
+        pListEntries->second >>= vListEntries;
+        for (OUString const& i : std::as_const(vListEntries))
+            m_xTreeView->append_text(i);
+    }
+
+    if (!vListEntries.hasElements())
+    {
+        m_xTreeView->append_text(SwResId(STR_DROP_DOWN_EMPTY_LIST));
+    }
 
-    if (fieldBM != nullptr)
+    // Select the current one
+    sw::mark::IFieldmark::parameter_map_t::const_iterator pResult
+        = pParameters->find(ODF_FORMDROPDOWN_RESULT);
+    if (pResult != pParameters->end())
     {
-        const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
fieldBM->GetParameters();
-
-        sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries
-            = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
-        css::uno::Sequence<OUString> vListEntries;
-        if (pListEntries != pParameters->end())
-        {
-            pListEntries->second >>= vListEntries;
-            for (OUString const& i : std::as_const(vListEntries))
-                rTreeView.append_text(i);
-        }
-
-        if (!vListEntries.hasElements())
-        {
-            rTreeView.append_text(SwResId(STR_DROP_DOWN_EMPTY_LIST));
-        }
-
-        // Select the current one
-        sw::mark::IFieldmark::parameter_map_t::const_iterator pResult
-            = pParameters->find(ODF_FORMDROPDOWN_RESULT);
-        if (pResult != pParameters->end())
-        {
-            sal_Int32 nSelection = -1;
-            pResult->second >>= nSelection;
-            rTreeView.set_cursor(nSelection);
-            rTreeView.select(nSelection);
-        }
+        sal_Int32 nSelection = -1;
+        pResult->second >>= nSelection;
+        m_xTreeView->set_cursor(nSelection);
+        m_xTreeView->select(nSelection);
     }
 
-    auto nHeight = rTreeView.get_height_rows(
+    auto nHeight = m_xTreeView->get_height_rows(
         
std::min<int>(Application::GetSettings().GetStyleSettings().GetListBoxMaximumLineCount(),
-                      rTreeView.n_children()));
-    rTreeView.set_size_request(-1, nHeight);
-    Size lbSize(rTreeView.get_preferred_size());
+                      m_xTreeView->n_children()));
+    m_xTreeView->set_size_request(-1, nHeight);
+    Size lbSize(m_xTreeView->get_preferred_size());
     lbSize.AdjustWidth(4);
     lbSize.AdjustHeight(4);
+    auto nMinListWidth = GetSizePixel().Width();
     lbSize.setWidth(std::max(lbSize.Width(), nMinListWidth));
-    m_xListBox->SetSizePixel(lbSize);
-    rTreeView.connect_row_activated(LINK(this, SwFieldDialog, 
MyListBoxHandler));
-    rTreeView.connect_key_press(LINK(this, SwFieldDialog, KeyInputHdl));
-    m_xListBox->Show();
-
-    rTreeView.grab_focus();
-
-    SetSizePixel(lbSize);
-}
-
-SwFieldDialog::~SwFieldDialog() { disposeOnce(); }
-
-void SwFieldDialog::dispose()
-{
-    m_xListBox.disposeAndClear();
-    FloatingWindow::dispose();
+    m_xTreeView->set_size_request(lbSize.Width(), lbSize.Height());
 }
 
-IMPL_LINK(SwFieldDialog, MyListBoxHandler, weld::TreeView&, rBox, bool)
+IMPL_LINK(DropDownFormFieldButton, MyListBoxHandler, weld::TreeView&, rBox, 
bool)
 {
     OUString sSelection = rBox.get_selected_text();
     if (sSelection == SwResId(STR_DROP_DOWN_EMPTY_LIST))
     {
-        EndPopupMode();
+        m_xFieldPopup->popdown();
         return true;
     }
 
     sal_Int32 nSelection = rBox.get_selected_index();
     if (nSelection >= 0)
     {
-        (*m_pFieldmark->GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= 
nSelection;
-        m_pFieldmark->Invalidate();
+        (*m_rFieldmark.GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= 
nSelection;
+        m_rFieldmark.Invalidate();
         SwView& rView = static_cast<SwEditWin*>(GetParent())->GetView();
         rView.GetDocShell()->SetModified();
     }
 
-    EndPopupMode();
+    m_xFieldPopup->popdown();
 
     return true;
 }
 
-IMPL_STATIC_LINK(SwFieldDialog, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
-{
-    bool bDone = false;
-    vcl::KeyCode aCode = rKeyEvent.GetKeyCode();
-    // nowhere to tab to
-    if (aCode.GetCode() == KEY_TAB)
-        bDone = true;
-    return bDone;
-}
-
 DropDownFormFieldButton::DropDownFormFieldButton(SwEditWin* pEditWin,
                                                  sw::mark::DropDownFieldmark& 
rFieldmark)
     : FormFieldButton(pEditWin, rFieldmark)
@@ -169,10 +96,22 @@ 
DropDownFormFieldButton::DropDownFormFieldButton(SwEditWin* pEditWin,
 
 DropDownFormFieldButton::~DropDownFormFieldButton() { disposeOnce(); }
 
-void DropDownFormFieldButton::InitPopup()
+void DropDownFormFieldButton::LaunchPopup()
+{
+    m_xFieldPopupBuilder.reset(
+        Application::CreateBuilder(GetFrameWeld(), 
"modules/swriter/ui/formdropdown.ui"));
+    m_xFieldPopup = m_xFieldPopupBuilder->weld_popover("FormDropDown");
+    m_xTreeView = m_xFieldPopupBuilder->weld_tree_view("list");
+    InitDropdown();
+    m_xTreeView->connect_row_activated(LINK(this, DropDownFormFieldButton, 
MyListBoxHandler));
+    FormFieldButton::LaunchPopup();
+    m_xTreeView->grab_focus();
+}
+
+void DropDownFormFieldButton::DestroyPopup()
 {
-    m_pFieldPopup = 
VclPtr<SwFieldDialog>::Create(static_cast<SwEditWin*>(GetParent()),
-                                                  &m_rFieldmark, 
GetSizePixel().Width());
+    m_xTreeView.reset();
+    FormFieldButton::DestroyPopup();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/core/crsr/FormFieldButton.cxx 
b/sw/source/core/crsr/FormFieldButton.cxx
index 8ae84826a3f9..0f13494b648e 100644
--- a/sw/source/core/crsr/FormFieldButton.cxx
+++ b/sw/source/core/crsr/FormFieldButton.cxx
@@ -11,7 +11,7 @@
 #include <edtwin.hxx>
 #include <basegfx/color/bcolortools.hxx>
 #include <bookmrk.hxx>
-#include <vcl/floatwin.hxx>
+#include <vcl/weldutils.hxx>
 #include <vcl/event.hxx>
 
 FormFieldButton::FormFieldButton(SwEditWin* pEditWin, sw::mark::Fieldmark& 
rFieldmark)
@@ -29,9 +29,24 @@ FormFieldButton::FormFieldButton(SwEditWin* pEditWin, 
sw::mark::Fieldmark& rFiel
 
 FormFieldButton::~FormFieldButton() { disposeOnce(); }
 
+void FormFieldButton::LaunchPopup()
+{
+    m_xFieldPopup->connect_closed(LINK(this, DropDownFormFieldButton, 
FieldPopupModeEndHdl));
+
+    tools::Rectangle aRect(Point(0, 0), GetSizePixel());
+    weld::Window* pParent = weld::GetPopupParent(*this, aRect);
+    m_xFieldPopup->popup_at_rect(pParent, aRect);
+}
+
+void FormFieldButton::DestroyPopup()
+{
+    m_xFieldPopup.reset();
+    m_xFieldPopupBuilder.reset();
+}
+
 void FormFieldButton::dispose()
 {
-    m_pFieldPopup.disposeAndClear();
+    DestroyPopup();
     Control::dispose();
 }
 
@@ -63,23 +78,13 @@ void FormFieldButton::CalcPosAndSize(const SwRect& 
rPortionPaintArea)
 
 void FormFieldButton::MouseButtonDown(const MouseEvent&)
 {
-    assert(GetParent());
-
-    // sets m_pFieldPopup
-    InitPopup();
-
-    m_pFieldPopup->SetPopupModeEndHdl(LINK(this, DropDownFormFieldButton, 
FieldPopupModeEndHdl));
-
-    Size aSize = GetSizePixel();
-    Point aPos(GetParent()->OutputToScreenPixel(GetPosPixel()));
-    tools::Rectangle aRect(aPos, aSize);
-    m_pFieldPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down | 
FloatWinPopupFlags::GrabFocus);
+    LaunchPopup();
     Invalidate();
 }
 
-IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, FloatingWindow*, void)
+IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, weld::Popover&, void)
 {
-    m_pFieldPopup.disposeAndClear();
+    DestroyPopup();
     m_rFieldmark.Invalidate();
     // Hide the button here and make it visible later, to make transparent 
background work with SAL_USE_VCLPLUGIN=gen
     Show(false);
@@ -99,7 +104,7 @@ void FormFieldButton::Paint(vcl::RenderContext& 
rRenderContext, const tools::Rec
 
     //const StyleSettings& rSettings = 
Application::GetSettings().GetStyleSettings();
     Color aLineColor = COL_BLACK;
-    Color aFillColor(lcl_GetFillColor(aLineColor.getBColor(), (m_pFieldPopup ? 
0.5 : 0.75)));
+    Color aFillColor(lcl_GetFillColor(aLineColor.getBColor(), (m_xFieldPopup ? 
0.5 : 0.75)));
 
     // Draw the frame around the field
     // GTK3 backend cuts down the frame's top and left border, to avoid that 
add a padding around the frame
diff --git a/sw/source/core/inc/DateFormFieldButton.hxx 
b/sw/source/core/inc/DateFormFieldButton.hxx
index 60aad2777aba..a03bfc9117be 100644
--- a/sw/source/core/inc/DateFormFieldButton.hxx
+++ b/sw/source/core/inc/DateFormFieldButton.hxx
@@ -13,7 +13,6 @@
 #include "FormFieldButton.hxx"
 
 class SwEditWin;
-class FloatingWindow;
 class SvNumberFormatter;
 namespace sw::mark
 {
@@ -26,15 +25,21 @@ class DateFieldmark;
  */
 class DateFormFieldButton : public FormFieldButton
 {
+private:
+    SvNumberFormatter* m_pNumberFormatter;
+    sw::mark::DateFieldmark* m_pDateFieldmark;
+
+    std::unique_ptr<weld::Calendar> m_xCalendar;
+
+    DECL_LINK(ImplSelectHdl, weld::Calendar&, void);
+
 public:
     DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& 
rFieldMark,
                         SvNumberFormatter* pNumberFormatter);
     virtual ~DateFormFieldButton() override;
 
-    virtual void InitPopup() override;
-
-private:
-    SvNumberFormatter* m_pNumberFormatter;
+    virtual void LaunchPopup() override;
+    virtual void DestroyPopup() override;
 };
 
 #endif
diff --git a/sw/source/core/inc/DropDownFormFieldButton.hxx 
b/sw/source/core/inc/DropDownFormFieldButton.hxx
index ffaa2af2d2b8..9853c57a3116 100644
--- a/sw/source/core/inc/DropDownFormFieldButton.hxx
+++ b/sw/source/core/inc/DropDownFormFieldButton.hxx
@@ -7,13 +7,11 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#ifndef INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX
-#define INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX
+#pragma once
 
 #include "FormFieldButton.hxx"
 
 class SwEditWin;
-class FloatingWindow;
 namespace sw::mark
 {
 class DropDownFieldmark;
@@ -25,13 +23,19 @@ class DropDownFieldmark;
  */
 class DropDownFormFieldButton : public FormFieldButton
 {
+private:
+    std::unique_ptr<weld::TreeView> m_xTreeView;
+
+    DECL_LINK(MyListBoxHandler, weld::TreeView&, bool);
+
+    void InitDropdown();
+
 public:
     DropDownFormFieldButton(SwEditWin* pEditWin, sw::mark::DropDownFieldmark& 
rFieldMark);
     virtual ~DropDownFormFieldButton() override;
 
-    virtual void InitPopup() override;
+    virtual void LaunchPopup() override;
+    virtual void DestroyPopup() override;
 };
 
-#endif
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/core/inc/FormFieldButton.hxx 
b/sw/source/core/inc/FormFieldButton.hxx
index 4dec3b752d13..22a9b3e8c7b0 100644
--- a/sw/source/core/inc/FormFieldButton.hxx
+++ b/sw/source/core/inc/FormFieldButton.hxx
@@ -10,10 +10,10 @@
 #pragma once
 
 #include <vcl/ctrl.hxx>
+#include <vcl/weld.hxx>
 #include <swrect.hxx>
 
 class SwEditWin;
-class FloatingWindow;
 namespace sw::mark
 {
 class Fieldmark;
@@ -32,19 +32,21 @@ public:
     void CalcPosAndSize(const SwRect& rPortionPaintArea);
 
     virtual void MouseButtonDown(const MouseEvent& rMEvt) override;
-    DECL_LINK(FieldPopupModeEndHdl, FloatingWindow*, void);
+    DECL_LINK(FieldPopupModeEndHdl, weld::Popover&, void);
 
     virtual void Paint(vcl::RenderContext& rRenderContext, const 
tools::Rectangle& rRect) override;
     virtual WindowHitTest ImplHitTest(const Point& rFramePos) override;
 
-    virtual void InitPopup() = 0;
+    virtual void LaunchPopup();
+    virtual void DestroyPopup();
 
 private:
     tools::Rectangle m_aFieldFramePixel;
 
 protected:
     sw::mark::Fieldmark& m_rFieldmark;
-    VclPtr<FloatingWindow> m_pFieldPopup;
+    std::unique_ptr<weld::Builder> m_xFieldPopupBuilder;
+    std::unique_ptr<weld::Popover> m_xFieldPopup;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/uiconfig/swriter/ui/calendar.ui 
b/sw/uiconfig/swriter/ui/calendar.ui
index 760309ac0009..5c8d3eb43bfd 100644
--- a/sw/uiconfig/swriter/ui/calendar.ui
+++ b/sw/uiconfig/swriter/ui/calendar.ui
@@ -1,25 +1,31 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.2 -->
+<!-- Generated with glade 3.38.2 -->
 <interface domain="sw">
   <requires lib="gtk+" version="3.20"/>
-  <object class="GtkBox" id="Calendar">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="orientation">vertical</property>
-    <property name="spacing">6</property>
+  <object class="GtkPopover" id="Calendar">
+    <property name="can-focus">False</property>
+    <property name="position">bottom</property>
     <child>
-      <object class="GtkCalendar" id="date">
+      <object class="GtkBox">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="year">2019</property>
-        <property name="month">1</property>
-        <property name="day">14</property>
+        <property name="can-focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkCalendar" id="date">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="year">2019</property>
+            <property name="month">1</property>
+            <property name="day">14</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
       </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">True</property>
-        <property name="position">0</property>
-      </packing>
     </child>
   </object>
 </interface>
diff --git a/sw/uiconfig/swriter/ui/formdropdown.ui 
b/sw/uiconfig/swriter/ui/formdropdown.ui
index 9a35356a9770..8863f52659e3 100644
--- a/sw/uiconfig/swriter/ui/formdropdown.ui
+++ b/sw/uiconfig/swriter/ui/formdropdown.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.2 -->
+<!-- Generated with glade 3.38.2 -->
 <interface domain="sw">
   <requires lib="gtk+" version="3.20"/>
   <object class="GtkTreeStore" id="liststore1">
@@ -10,53 +10,59 @@
       <column type="gchararray"/>
     </columns>
   </object>
-  <object class="GtkBox" id="FormDropDown">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="hexpand">True</property>
-    <property name="vexpand">True</property>
-    <property name="orientation">vertical</property>
-    <property name="spacing">6</property>
+  <object class="GtkPopover" id="FormDropDown">
+    <property name="can-focus">False</property>
+    <property name="position">bottom</property>
     <child>
-      <object class="GtkScrolledWindow">
+      <object class="GtkBox">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
+        <property name="can-focus">False</property>
         <property name="hexpand">True</property>
         <property name="vexpand">True</property>
-        <property name="hscrollbar_policy">never</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
         <child>
-          <object class="GtkTreeView" id="list">
+          <object class="GtkScrolledWindow">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
+            <property name="can-focus">True</property>
+            <property name="hexpand">True</property>
             <property name="vexpand">True</property>
-            <property name="model">liststore1</property>
-            <property name="headers_visible">False</property>
-            <property name="headers_clickable">False</property>
-            <property name="search_column">0</property>
-            <property name="hover_selection">True</property>
-            <property name="show_expanders">False</property>
-            <property name="activate_on_single_click">True</property>
-            <child internal-child="selection">
-              <object class="GtkTreeSelection" id="treeview-selection1"/>
-            </child>
+            <property name="hscrollbar-policy">never</property>
             <child>
-              <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+              <object class="GtkTreeView" id="list">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="vexpand">True</property>
+                <property name="model">liststore1</property>
+                <property name="headers-visible">False</property>
+                <property name="headers-clickable">False</property>
+                <property name="search-column">0</property>
+                <property name="hover-selection">True</property>
+                <property name="show-expanders">False</property>
+                <property name="activate-on-single-click">True</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection"/>
+                </child>
                 <child>
-                  <object class="GtkCellRendererText" id="cellrenderertext1"/>
-                  <attributes>
-                    <attribute name="text">0</attribute>
-                  </attributes>
+                  <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                    <child>
+                      <object class="GtkCellRendererText" 
id="cellrenderertext1"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
                 </child>
               </object>
             </child>
           </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
         </child>
       </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">True</property>
-        <property name="position">0</property>
-      </packing>
     </child>
   </object>
 </interface>
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index b8c5888572d0..4322cb242b1b 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -121,6 +121,8 @@ public:
 
     virtual std::unique_ptr<weld::Menu> weld_menu(const OString& id) override;
 
+    virtual std::unique_ptr<weld::Popover> weld_popover(const OString& id) 
override;
+
     virtual std::unique_ptr<weld::Toolbar> weld_toolbar(const OString& id) 
override;
 
     virtual std::unique_ptr<weld::SizeGroup> create_size_group() override;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 7bb05907ecba..6c86215bd808 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -6611,6 +6611,54 @@ IMPL_LINK(SalInstanceEntryTreeView, AutocompleteHdl, 
Edit&, rEdit, void)
     }
 }
 
+namespace
+{
+class SalInstancePopover : public SalInstanceContainer, public virtual 
weld::Popover
+{
+private:
+    VclPtr<DockingWindow> m_xPopover;
+
+    DECL_LINK(PopupModeEndHdl, FloatingWindow*, void);
+
+public:
+    SalInstancePopover(DockingWindow* pPopover, SalInstanceBuilder* pBuilder, 
bool bTakeOwnership)
+        : SalInstanceContainer(pPopover, pBuilder, bTakeOwnership)
+        , m_xPopover(pPopover)
+    {
+    }
+
+    virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& 
rRect) override
+    {
+        SalInstanceWidget* pVclWidget = 
dynamic_cast<SalInstanceWidget*>(pParent);
+        assert(pVclWidget);
+        vcl::Window* pWidget = pVclWidget->getWidget();
+
+        tools::Rectangle aRect;
+        Point aPt = pWidget->OutputToScreenPixel(rRect.TopLeft());
+        aRect.SetLeft(aPt.X());
+        aRect.SetTop(aPt.Y());
+        aPt = pWidget->OutputToScreenPixel(rRect.BottomRight());
+        aRect.SetRight(aPt.X());
+        aRect.SetBottom(aPt.Y());
+
+        FloatWinPopupFlags nFlags = FloatWinPopupFlags::Down | 
FloatWinPopupFlags::GrabFocus;
+        m_xPopover->EnableDocking();
+        DockingManager* pDockingManager = vcl::Window::GetDockingManager();
+        pDockingManager->SetPopupModeEndHdl(m_xPopover,
+                                            LINK(this, SalInstancePopover, 
PopupModeEndHdl));
+        pDockingManager->StartPopupMode(m_xPopover, aRect, nFlags);
+    }
+
+    virtual void popdown() override
+    {
+        vcl::Window::GetDockingManager()->EndPopupMode(m_xPopover);
+        m_xPopover->EnableDocking(false);
+    }
+};
+}
+
+IMPL_LINK_NOARG(SalInstancePopover, PopupModeEndHdl, FloatingWindow*, void) { 
signal_closed(); }
+
 SalInstanceBuilder::SalInstanceBuilder(vcl::Window* pParent, const OUString& 
rUIRoot,
                                        const OUString& rUIFile,
                                        const 
css::uno::Reference<css::frame::XFrame>& rFrame)
@@ -6922,6 +6970,20 @@ std::unique_ptr<weld::Menu> 
SalInstanceBuilder::weld_menu(const OString& id)
     return pMenu ? std::make_unique<SalInstanceMenu>(pMenu, true) : nullptr;
 }
 
+std::unique_ptr<weld::Popover> SalInstanceBuilder::weld_popover(const OString& 
id)
+{
+    DockingWindow* pDockingWindow = m_xBuilder->get<DockingWindow>(id);
+    std::unique_ptr<weld::Popover> pRet(
+        pDockingWindow ? new SalInstancePopover(pDockingWindow, this, false) : 
nullptr);
+    if (pDockingWindow)
+    {
+        assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
+        m_aOwnedToplevel.set(pDockingWindow);
+        m_xBuilder->drop_ownership(pDockingWindow);
+    }
+    return pRet;
+}
+
 std::unique_ptr<weld::Toolbar> SalInstanceBuilder::weld_toolbar(const OString& 
id)
 {
     ToolBox* pToolBox = m_xBuilder->get<ToolBox>(id);
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 1c9e284be0c3..682f4ebe757f 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -1754,6 +1754,30 @@ namespace
         return AllSettings::GetLayoutRTL();
     }
 
+    GtkWidget* getPopupRect(GtkWidget* pWidget, const tools::Rectangle& 
rInRect, GdkRectangle& rOutRect)
+    {
+        if (GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pWidget))
+        {
+            // this is the relatively unusual case where pParent is the 
toplevel GtkSalFrame and not a stock GtkWidget
+            // so use the same style of logic as 
GtkSalMenu::ShowNativePopupMenu to get the right position
+            tools::Rectangle aFloatRect = 
FloatingWindow::ImplConvertToAbsPos(pFrame->GetWindow(), rInRect);
+            aFloatRect.Move(-pFrame->maGeometry.nX, -pFrame->maGeometry.nY);
+
+            rOutRect = GdkRectangle{static_cast<int>(aFloatRect.Left()), 
static_cast<int>(aFloatRect.Top()),
+                                    static_cast<int>(aFloatRect.GetWidth()), 
static_cast<int>(aFloatRect.GetHeight())};
+
+            pWidget = pFrame->getMouseEventWidget();
+        }
+        else
+        {
+            rOutRect = GdkRectangle{static_cast<int>(rInRect.Left()), 
static_cast<int>(rInRect.Top()),
+                                 static_cast<int>(rInRect.GetWidth()), 
static_cast<int>(rInRect.GetHeight())};
+            if (SwapForRTL(pWidget))
+                rOutRect.x = gtk_widget_get_allocated_width(pWidget) - 
rOutRect.width - 1 - rOutRect.x;
+        }
+        return pWidget;
+    }
+
     void replaceWidget(GtkWidget* pWidget, GtkWidget* pReplacement)
     {
         // remove the widget and replace it with pReplacement
@@ -8150,25 +8174,7 @@ public:
         if (gtk_check_version(3, 22, 0) == nullptr)
         {
             GdkRectangle aRect;
-            if (GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pWidget))
-            {
-                // this is the relatively unusual case where pParent is the 
toplevel GtkSalFrame and not a stock GtkWidget
-                // so use the same style of logic as 
GtkSalMenu::ShowNativePopupMenu to get the right position
-                tools::Rectangle aFloatRect = 
FloatingWindow::ImplConvertToAbsPos(pFrame->GetWindow(), rRect);
-                aFloatRect.Move(-pFrame->maGeometry.nX, 
-pFrame->maGeometry.nY);
-
-                aRect = GdkRectangle{static_cast<int>(aFloatRect.Left()), 
static_cast<int>(aFloatRect.Top()),
-                                     static_cast<int>(aFloatRect.GetWidth()), 
static_cast<int>(aFloatRect.GetHeight())};
-
-                pWidget = pFrame->getMouseEventWidget();
-            }
-            else
-            {
-                aRect = GdkRectangle{static_cast<int>(rRect.Left()), 
static_cast<int>(rRect.Top()),
-                                     static_cast<int>(rRect.GetWidth()), 
static_cast<int>(rRect.GetHeight())};
-                if (SwapForRTL(pWidget))
-                    aRect.x = gtk_widget_get_allocated_width(pWidget) - 
aRect.width - 1 - aRect.x;
-            }
+            pWidget = getPopupRect(pWidget, rRect, aRect);
 
             // Send a keyboard event through gtk_main_do_event to toggle any 
active tooltip offs
             // before trying to launch the menu
@@ -16579,6 +16585,74 @@ public:
 
         return false;
     }
+
+class GtkInstancePopover : public GtkInstanceContainer, public virtual 
weld::Popover
+{
+private:
+    GtkPopover* m_pPopover;
+    gulong m_nSignalId;
+    ImplSVEvent* m_pClosedEvent;
+
+    static void signalClosed(GtkPopover*, gpointer widget)
+    {
+        GtkInstancePopover* pThis = static_cast<GtkInstancePopover*>(widget);
+        // call signal-closed async so the closed callback isn't called
+        // whilc the GtkPopover handler is still in-execution
+        pThis->launch_signal_closed();
+    }
+
+    DECL_LINK(async_signal_closed, void*, void);
+
+    void launch_signal_closed()
+    {
+        if (m_pClosedEvent)
+            Application::RemoveUserEvent(m_pClosedEvent);
+        m_pClosedEvent = Application::PostUserEvent(LINK(this, 
GtkInstancePopover, async_signal_closed));
+    }
+
+public:
+    GtkInstancePopover(GtkPopover* pPopover, GtkInstanceBuilder* pBuilder, 
bool bTakeOwnership)
+        : GtkInstanceContainer(GTK_CONTAINER(pPopover), pBuilder, 
bTakeOwnership)
+        , m_pPopover(pPopover)
+        , m_nSignalId(g_signal_connect(m_pPopover, "closed", 
G_CALLBACK(signalClosed), this))
+        , m_pClosedEvent(nullptr)
+    {
+    }
+
+    virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& 
rRect) override
+    {
+        GtkInstanceWidget* pGtkWidget = 
dynamic_cast<GtkInstanceWidget*>(pParent);
+        assert(pGtkWidget);
+
+        GtkWidget* pWidget = pGtkWidget->getWidget();
+
+        GdkRectangle aRect;
+        pWidget = getPopupRect(pWidget, rRect, aRect);
+
+        gtk_popover_set_relative_to(m_pPopover, pWidget);
+        gtk_popover_set_pointing_to(m_pPopover, &aRect);
+        gtk_popover_popup(m_pPopover);
+    }
+
+    virtual void popdown() override
+    {
+        gtk_popover_popdown(m_pPopover);
+    }
+
+    virtual ~GtkInstancePopover() override
+    {
+        if (m_pClosedEvent)
+            Application::RemoveUserEvent(m_pClosedEvent);
+        g_signal_handler_disconnect(m_pPopover, m_nSignalId);
+    }
+};
+
+IMPL_LINK_NOARG(GtkInstancePopover, async_signal_closed, void*, void)
+{
+    m_pClosedEvent = nullptr;
+    signal_closed();
+}
+
 }
 
 namespace
@@ -17375,6 +17449,14 @@ public:
         return std::make_unique<GtkInstanceMenu>(pMenu, true);
     }
 
+    virtual std::unique_ptr<weld::Popover> weld_popover(const OString &id) 
override
+    {
+        GtkPopover* pPopover = GTK_POPOVER(gtk_builder_get_object(m_pBuilder, 
id.getStr()));
+        if (!pPopover)
+            return nullptr;
+        return std::make_unique<GtkInstancePopover>(pPopover, this, true);
+    }
+
     virtual std::unique_ptr<weld::Toolbar> weld_toolbar(const OString &id) 
override
     {
         GtkToolbar* pToolbar = GTK_TOOLBAR(gtk_builder_get_object(m_pBuilder, 
id.getStr()));
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to