From 0c04966dc358a164304a28fd15abe36f7c41116b Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 24 Nov 2024 11:50:04 +0000 Subject: [PATCH] Fix #13022: Ensure minimum size of scrollbar slider. (#13119) When there are many more items than fit in a list, the scrollbar slider scales to fit but there is no minimum size. It becomes too small to click on and use. Ensure scrollbar slider is at least the same size as the buttons either end. --- src/widget.cpp | 14 ++++++++------ src/window.cpp | 6 ++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/widget.cpp b/src/widget.cpp index 6308f3ebc5..9d131c4fc9 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -145,15 +145,17 @@ static Point HandleScrollbarHittest(const Scrollbar *sb, int top, int bottom, bo top += button_size; // top points to just below the up-button bottom -= button_size; // bottom points to top of the down-button - int height = (bottom - top); - int pos = sb->GetPosition(); int count = sb->GetCount(); int cap = sb->GetCapacity(); - if (count != 0) top += height * pos / count; + if (count > cap) { + int height = (bottom - top); + int slider_height = std::max(button_size, cap * height / count); + height -= slider_height; - if (cap > count) cap = count; - if (count != 0) bottom -= (count - pos - cap) * height / count; + top += height * sb->GetPosition() / (count - cap); + bottom = top + slider_height; + } Point pt; if (horizontal && _current_text_dir == TD_RTL) { @@ -216,7 +218,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in changed = sb->UpdatePosition(rtl ? -1 : 1, Scrollbar::SS_BIG); } else { _scrollbar_start_pos = pt.x - mi - button_size; - _scrollbar_size = ma - mi - button_size * 2; + _scrollbar_size = ma - mi - button_size * 2 - (pt.y - pt.x); w->mouse_capture_widget = sb->index; _cursorpos_drag_start = _cursor.pos; } diff --git a/src/window.cpp b/src/window.cpp index e69c50977c..bb3a9272cd 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2308,8 +2308,10 @@ static void HandleScrollbarScrolling(Window *w) } /* Find the item we want to move to. SetPosition will make sure it's inside bounds. */ - int pos = RoundDivSU((i + _scrollbar_start_pos) * sb->GetCount(), _scrollbar_size); - if (rtl) pos = sb->GetCount() - sb->GetCapacity() - pos; + int range = sb->GetCount() - sb->GetCapacity(); + + int pos = RoundDivSU((i + _scrollbar_start_pos) * range, _scrollbar_size); + if (rtl) pos = range - pos; if (sb->SetPosition(pos)) w->SetDirty(); }