include/vcl/weld.hxx          |   10 +++++++++-
 vcl/inc/salvtables.hxx        |    3 ++-
 vcl/source/app/salvtables.cxx |   11 ++++++++---
 vcl/unx/gtk3/gtkinst.cxx      |   21 +++++++++++++++++++--
 4 files changed, 38 insertions(+), 7 deletions(-)

New commits:
commit 6b4b82626a30418c2d566c4fc1ecfe559557bf2b
Author:     Caolán McNamara <[email protected]>
AuthorDate: Wed Nov 17 17:00:58 2021 +0000
Commit:     Caolán McNamara <[email protected]>
CommitDate: Wed Nov 17 20:49:22 2021 +0100

    allow menu placement either under or at end
    
    Change-Id: Id76cbe69464f439eec900bf9b80b0c63d99b6597
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125416
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index df036c8fde1a..b25e9abe5383 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -2277,6 +2277,12 @@ private:
     virtual void click(const Point& rPos) = 0;
 };
 
+enum class Placement
+{
+    Under,
+    End
+};
+
 class VCL_DLLPUBLIC Menu
 {
 protected:
@@ -2285,7 +2291,9 @@ protected:
     void signal_activate(const OString& rIdent) { m_aActivateHdl.Call(rIdent); 
}
 
 public:
-    virtual OString popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle& rRect) = 0;
+    virtual OString popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle& rRect,
+                                  Placement ePlace = Placement::Under)
+        = 0;
 
     void connect_activate(const Link<const OString&, void>& rLink) { 
m_aActivateHdl = rLink; }
 
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index 57f6149ff7bc..c97b39df575d 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -145,7 +145,8 @@ private:
 
 public:
     SalInstanceMenu(PopupMenu* pMenu, bool bTakeOwnership);
-    virtual OString popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle& rRect) override;
+    virtual OString popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle& rRect,
+                                  weld::Placement ePlace = 
weld::Placement::Under) override;
     virtual void set_sensitive(const OString& rIdent, bool bSensitive) 
override;
     virtual bool get_sensitive(const OString& rIdent) const override;
     virtual void set_active(const OString& rIdent, bool bActive) override;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 792534a92517..987a9ffe2aeb 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -772,12 +772,17 @@ SalInstanceMenu::SalInstanceMenu(PopupMenu* pMenu, bool 
bTakeOwnership)
     m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
     m_xMenu->SetSelectHdl(LINK(this, SalInstanceMenu, SelectMenuHdl));
 }
-OString SalInstanceMenu::popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle& rRect)
+OString SalInstanceMenu::popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle& rRect,
+                                       weld::Placement ePlace)
 {
     SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pParent);
     assert(pVclWidget);
-    m_xMenu->Execute(pVclWidget->getWidget(), rRect,
-                     PopupMenuFlags::ExecuteDown | 
PopupMenuFlags::NoMouseUpClose);
+    PopupMenuFlags eFlags = PopupMenuFlags::NoMouseUpClose;
+    if (ePlace == weld::Placement::Under)
+        eFlags = eFlags | PopupMenuFlags::ExecuteDown;
+    else
+        eFlags = eFlags | PopupMenuFlags::ExecuteRight;
+    m_xMenu->Execute(pVclWidget->getWidget(), rRect, eFlags);
     return m_xMenu->GetCurItemIdent();
 }
 void SalInstanceMenu::set_sensitive(const OString& rIdent, bool bSensitive)
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 93035fd27cbb..6ce18a346ac4 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -10718,7 +10718,7 @@ public:
 #endif
     }
 
-    virtual OString popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle &rRect) override
+    virtual OString popup_at_rect(weld::Widget* pParent, const 
tools::Rectangle &rRect, weld::Placement ePlace) override
     {
         m_sActivated.clear();
 
@@ -10743,6 +10743,15 @@ public:
         GtkWidget* pOrigParent = gtk_widget_get_parent(GTK_WIDGET(m_pMenu));
         gtk_widget_set_parent(GTK_WIDGET(m_pMenu), pWidget);
         gtk_popover_set_pointing_to(GTK_POPOVER(m_pMenu), &aRect);
+        if (ePlace == weld::Placement::Under)
+            gtk_popover_set_position(GTK_POPOVER(m_pMenu), GTK_POS_BOTTOM);
+        else
+        {
+            if (SwapForRTL(pWidget))
+                gtk_popover_set_position(GTK_POPOVER(m_pMenu), GTK_POS_LEFT);
+            else
+                gtk_popover_set_position(GTK_POPOVER(m_pMenu), GTK_POS_RIGHT);
+        }
         gtk_popover_popup(GTK_POPOVER(m_pMenu));
 #else
         gulong nSignalId = g_signal_connect_swapped(G_OBJECT(m_pMenu), 
"deactivate", G_CALLBACK(g_main_loop_quit), pLoop);
@@ -10765,7 +10774,15 @@ public:
             if (!pTriggerEvent)
                 pTriggerEvent = pKeyEvent;
 
-            gtk_menu_popup_at_rect(m_pMenu, widget_get_surface(pWidget), 
&aRect, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, pTriggerEvent);
+            if (ePlace == weld::Placement::Under)
+                gtk_menu_popup_at_rect(m_pMenu, widget_get_surface(pWidget), 
&aRect, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, pTriggerEvent);
+            else
+            {
+                if (SwapForRTL(pWidget))
+                    gtk_menu_popup_at_rect(m_pMenu, 
widget_get_surface(pWidget), &aRect, GDK_GRAVITY_NORTH_WEST, 
GDK_GRAVITY_NORTH_EAST, pTriggerEvent);
+                else
+                    gtk_menu_popup_at_rect(m_pMenu, 
widget_get_surface(pWidget), &aRect, GDK_GRAVITY_NORTH_EAST, 
GDK_GRAVITY_NORTH_WEST, pTriggerEvent);
+            }
 
             gdk_event_free(pKeyEvent);
         }

Reply via email to