vcl/inc/listbox.hxx                |    3 +
 vcl/source/control/combobox.cxx    |    2 -
 vcl/source/control/imp_listbox.cxx |   60 +++++++++++++++++++++++++++----------
 vcl/source/control/listbox.cxx     |    2 -
 4 files changed, 48 insertions(+), 19 deletions(-)

New commits:
commit 794946c9a7bd876468c02fc6b254f4a2536b6a93
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Jun 27 11:06:53 2025 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Jun 27 14:53:49 2025 +0200

    Resolves: tdf#136943 limit combobox popups to max available below/above 
height
    
    If the popup won't fit either above/below then force the menu to scroll
    if it won't fit
    
    Change-Id: I03c051606ce29e2eba7046248e05c25fbdbded1a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187096
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins

diff --git a/vcl/inc/listbox.hxx b/vcl/inc/listbox.hxx
index 725e0d3c7c49..b05cee40fa97 100644
--- a/vcl/inc/listbox.hxx
+++ b/vcl/inc/listbox.hxx
@@ -522,7 +522,8 @@ public:
 
     void            SetAutoWidth( bool b )              { mbAutoWidth = b; }
 
-    Size            CalcFloatSize() const;
+    tools::Rectangle GetParentRect() const;
+    Size            CalcFloatSize(const tools::Rectangle& rParentRect) const;
     void            StartFloat( bool bStartTracking );
 
     virtual void    setPosSizePixel( tools::Long nX, tools::Long nY,
diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx
index 7b1b2ab59b1e..a565e4028e16 100644
--- a/vcl/source/control/combobox.cxx
+++ b/vcl/source/control/combobox.cxx
@@ -587,7 +587,7 @@ void ComboBox::Resize()
     // adjust the size of the FloatingWindow even when invisible
     // as KEY_PGUP/DOWN is being processed...
     if (m_pFloatWin)
-        m_pFloatWin->SetSizePixel(m_pFloatWin->CalcFloatSize());
+        
m_pFloatWin->SetSizePixel(m_pFloatWin->CalcFloatSize(m_pFloatWin->GetParentRect()));
 }
 
 bool ComboBox::IsDropDownBox() const { return m_pFloatWin != nullptr; }
diff --git a/vcl/source/control/imp_listbox.cxx 
b/vcl/source/control/imp_listbox.cxx
index ab4c7d614685..73284a54de2c 100644
--- a/vcl/source/control/imp_listbox.cxx
+++ b/vcl/source/control/imp_listbox.cxx
@@ -2910,7 +2910,7 @@ void ImplListBoxFloatingWindow::Resize()
     FloatingWindow::Resize();
 }
 
-Size ImplListBoxFloatingWindow::CalcFloatSize() const
+Size ImplListBoxFloatingWindow::CalcFloatSize(const tools::Rectangle& 
rParentRect) const
 {
     Size aFloatSz( maPrefSz );
 
@@ -2927,6 +2927,8 @@ Size ImplListBoxFloatingWindow::CalcFloatSize() const
     if ( mnDDLineCount )
         aFloatSz.setHeight( nMaxHeight );
 
+    AbsoluteScreenPixelRectangle aDesktopRect(GetDesktopRectPixel());
+
     if( mbAutoWidth )
     {
         // AutoSize first only for width...
@@ -2941,13 +2943,32 @@ Size ImplListBoxFloatingWindow::CalcFloatSize() const
             aFloatSz.AdjustWidth(nSBWidth );
         }
 
-        tools::Long nDesktopWidth = GetDesktopRectPixel().getOpenWidth();
+        tools::Long nDesktopWidth = aDesktopRect.getOpenWidth();
         if (aFloatSz.Width() > nDesktopWidth)
             // Don't exceed the desktop width.
             aFloatSz.setWidth( nDesktopWidth );
     }
 
-    tools::Long nDesktopHeight = GetDesktopRectPixel().getOpenHeight();
+    tools::Long nDesktopHeight = aDesktopRect.getOpenHeight();
+
+    //tdf#136943. If the popup won't fit either above/below then force the menu
+    //to scroll if it won't fit
+    {
+        const vcl::Window* pRef = this;
+        if ( pRef->GetParent() )
+            pRef = pRef->GetParent();
+
+        tools::Rectangle normRect( rParentRect );  // rRect is already 
relative to top-level window
+        normRect.SetPos( pRef->ScreenToOutputPixel( normRect.TopLeft() ) );
+
+        AbsoluteScreenPixelRectangle 
devRect(pRef->OutputToAbsoluteScreenPixel(normRect.TopLeft()),
+                                             
pRef->OutputToAbsoluteScreenPixel(normRect.BottomRight()));
+
+        tools::Long nHeightAbove = devRect.Top() - aDesktopRect.Top();
+        tools::Long nHeightBelow = aDesktopRect.Bottom() - devRect.Bottom();
+        nDesktopHeight = std::min(nDesktopHeight, std::max(nHeightAbove, 
nHeightBelow));
+    }
+
     if (aFloatSz.Height() > nDesktopHeight)
         aFloatSz.setHeight(nDesktopHeight);
 
@@ -2967,7 +2988,6 @@ Size ImplListBoxFloatingWindow::CalcFloatSize() const
     if ( nInnerHeight % nEntryHeight )
     {
         nInnerHeight /= nEntryHeight;
-        nInnerHeight++;
         nInnerHeight *= nEntryHeight;
         aFloatSz.setHeight( nInnerHeight + nTop + nBottom );
     }
@@ -2983,19 +3003,9 @@ Size ImplListBoxFloatingWindow::CalcFloatSize() const
     return aFloatSz;
 }
 
-void ImplListBoxFloatingWindow::StartFloat( bool bStartTracking )
+tools::Rectangle ImplListBoxFloatingWindow::GetParentRect() const
 {
-    if( IsInPopupMode() )
-        return;
-
-    Size aFloatSz = CalcFloatSize();
-
-    SetSizePixel( aFloatSz );
-    mpImplLB->SetSizePixel( GetOutputSizePixel() );
-
-    sal_Int32 nPos = mpImplLB->GetEntryList().GetSelectedEntryPos( 0 );
-    mnPopupModeStartSaveSelection = nPos;
-
+    // Get Rectangle at which popup will appear
     Size aSz = GetParent()->GetSizePixel();
     Point aPos = GetParent()->GetPosPixel();
     aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
@@ -3021,6 +3031,24 @@ void ImplListBoxFloatingWindow::StartFloat( bool 
bStartTracking )
     if( pGrandparent->GetOutDev()->ImplIsAntiparallel() )
         pGrandparentOutDev->ReMirror( aRect );
 
+    return aRect;
+}
+
+void ImplListBoxFloatingWindow::StartFloat( bool bStartTracking )
+{
+    if( IsInPopupMode() )
+        return;
+
+    tools::Rectangle aRect = GetParentRect();
+
+    Size aFloatSz = CalcFloatSize(aRect);
+
+    SetSizePixel( aFloatSz );
+    mpImplLB->SetSizePixel( GetOutputSizePixel() );
+
+    sal_Int32 nPos = mpImplLB->GetEntryList().GetSelectedEntryPos( 0 );
+    mnPopupModeStartSaveSelection = nPos;
+
     mpImplLB->GetMainWindow()->ResetLastPosPixel();
     // mouse-button right: close the List-Box-Float-win and don't stop the 
handling fdo#84795
     StartPopupMode( aRect, LISTBOX_FLOATWINPOPUPFLAGS );
diff --git a/vcl/source/control/listbox.cxx b/vcl/source/control/listbox.cxx
index 6c00d62f3a93..bd209e3d9c00 100644
--- a/vcl/source/control/listbox.cxx
+++ b/vcl/source/control/listbox.cxx
@@ -636,7 +636,7 @@ void ListBox::Resize()
 
     // Retain FloatingWindow size even when it's invisible, as we still 
process KEY_PGUP/DOWN ...
     if ( mpFloatWin )
-        mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
+        mpFloatWin->SetSizePixel( 
mpFloatWin->CalcFloatSize(mpFloatWin->GetParentRect()) );
 
     Control::Resize();
 }

Reply via email to