[Scummvm-git-logs] scummvm master -> c041092694285068d2a83f53fc7f6e460d4d1d8e
sev-
noreply at scummvm.org
Mon Apr 20 21:33:32 UTC 2026
This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
15a0877a89 GUI: Add accelerated wheel scrolling to FluidScroller
67facd983f GUI: Implement fluid wheel scrolling in AboutDialog
c1f0043775 GUI: Implement drag to scroll in Grid
15c1eaefcf GUI: Implement Fluid scroll in Launcher Grid
af56d299da GUI: Implement drag to scroll in List
cb71d7b6cf GUI: Implement Fluid scroll in Launcher List
a2abc4c1e5 GUI: Centralize mouse wheel handling in FluidScroller
5ef242d112 GUI: Implenet Fluid Scroll in Richtext widget
441f97f4e4 GUI: Implement drag to scroll in ScrollContainer
84dab33d07 GUI: Implenet Fluid Scroll in ScrollContainer
c041092694 GUI: Centralize scroll step size logic in FluidScroller
Commit: 15a0877a896273e891eb534220bf27010b2a2fbb
https://github.com/scummvm/scummvm/commit/15a0877a896273e891eb534220bf27010b2a2fbb
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Add accelerated wheel scrolling to FluidScroller
Changed paths:
gui/animation/FluidScroll.cpp
gui/animation/FluidScroll.h
diff --git a/gui/animation/FluidScroll.cpp b/gui/animation/FluidScroll.cpp
index 19220415dd9..d714f7d0d0b 100644
--- a/gui/animation/FluidScroll.cpp
+++ b/gui/animation/FluidScroll.cpp
@@ -97,6 +97,7 @@ FluidScroller::FluidScroller() :
_animationOffset(0.0f),
_maxScroll(0.0f),
_viewportHeight(0),
+ _lastWheelTime(0),
_initialVelocity(0.0f),
_lambda(0.0f),
_stretchDistance(0.0f),
@@ -111,6 +112,7 @@ void FluidScroller::setBounds(float maxScroll, int viewportHeight) {
void FluidScroller::reset() {
_mode = kModeNone;
_startTime = 0;
+ _lastWheelTime = 0;
_initialVelocity = 0.0f;
_scrollPosRaw = 0.0f;
_velocityTracker.reset();
@@ -134,8 +136,10 @@ float FluidScroller::setPosition(float pos, bool checkBound) {
}
void FluidScroller::startFling() {
- float velocity = _velocityTracker.calculateVelocity();
-
+ startFling(_velocityTracker.calculateVelocity());
+}
+
+void FluidScroller::startFling(float velocity) {
if (fabsf(velocity) < 0.1f) {
checkBoundaries();
return;
@@ -147,6 +151,24 @@ void FluidScroller::startFling() {
_animationOffset = _scrollPosRaw;
}
+void FluidScroller::feedWheel(uint32 time, float deltaY) {
+ uint32 dt = time - _lastWheelTime;
+ _lastWheelTime = time;
+
+ /*
+ * Cap the duration to prevent extreme high/low velocity
+ * Otherwise use the actual interval
+ */
+ uint32 effectiveDt = dt;
+ if (dt > 200)
+ effectiveDt = 200;
+ else if (dt < 20)
+ effectiveDt = 20;
+
+ float velocity = deltaY / (float)effectiveDt;
+ startFling(velocity);
+}
+
void FluidScroller::absorb(float velocity, float distance) {
_mode = kModeSpringBack;
_startTime = g_system->getMillis();
diff --git a/gui/animation/FluidScroll.h b/gui/animation/FluidScroll.h
index 80f1fbb0ec7..15e14f06ed1 100644
--- a/gui/animation/FluidScroll.h
+++ b/gui/animation/FluidScroll.h
@@ -58,6 +58,12 @@ public:
// Start a fling using the recorded velocity
void startFling();
+ // Start a fling with a specific initial velocity
+ void startFling(float velocity);
+
+ // Record a wheel tick and start/update a fling
+ void feedWheel(uint32 time, float deltaY);
+
// Check if there is an active animation (fling or spring-back)
bool isAnimating() const { return _mode != kModeNone; }
@@ -102,6 +108,7 @@ private:
};
VelocityTracker _velocityTracker;
+ uint32 _lastWheelTime;
Mode _mode;
uint32 _startTime;
Commit: 67facd983f0a25d3c1e4cae5b283c640e3cbf342
https://github.com/scummvm/scummvm/commit/67facd983f0a25d3c1e4cae5b283c640e3cbf342
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implement fluid wheel scrolling in AboutDialog
Changed paths:
gui/about.cpp
diff --git a/gui/about.cpp b/gui/about.cpp
index 64634d7e58e..c7968731761 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -443,12 +443,10 @@ void AboutDialog::handleMouseWheel(int x, int y, int direction) {
_autoScroll = false;
_fluidScroller->stopAnimation();
-
- _scrollPos += stepping;
- _scrollPos = _fluidScroller->setPosition(_scrollPos, true);
+ _fluidScroller->feedWheel(g_system->getMillis(), (float)stepping);
if (_scrollbar) {
- _scrollbar->_currentPos = (int)_scrollPos;
+ _scrollbar->_currentPos = (int)_fluidScroller->getVisualPosition();
_scrollbar->recalc();
}
Commit: c1f004377528ec18a844b5bc4bddcc83bcd2d5e3
https://github.com/scummvm/scummvm/commit/c1f004377528ec18a844b5bc4bddcc83bcd2d5e3
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implement drag to scroll in Grid
Changed paths:
gui/widgets/grid.cpp
gui/widgets/grid.h
diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index 8b8ab8a27a6..fc731d7a5f4 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -91,8 +91,8 @@ void GridItemWidget::drawWidget() {
// Check if this entry is in the selected entries list
bool isSelected = _grid->_selectedItems[_activeEntry->entryID];
- // Draw selection highlight if this entry is selected or hovered
- if (isSelected || _isHighlighted) {
+ // Draw selection highlight if this entry is selected or hovered (not while dragging)
+ if (isSelected || (_isHighlighted && !_grid->_isMouseDown)) {
Common::Rect r(_x - kMarginX, _y - kMarginY,
_x + _w + kMarginX, _y + _h + kMarginY);
// Draw a highlighted BG on hover
@@ -209,6 +209,50 @@ void GridItemWidget::handleMouseMoved(int x, int y, int button) {
if (!_isHighlighted) {
handleMouseEntered(button);
}
+ _grid->handleMouseMoved(x + _x, y + _y, button);
+}
+
+void GridItemWidget::doSelection() {
+ if (_activeEntry->isHeader) {
+ _grid->_selectedEntry = nullptr;
+ _grid->toggleGroup(_activeEntry->entryID);
+ } else if (_isHighlighted && isVisible()) {
+ _grid->_selectedEntry = _activeEntry;
+
+ if (!_grid->isMultiSelectEnabled()) {
+ _grid->clearSelection();
+ _grid->markSelectedItem(_activeEntry->entryID, true);
+ _grid->_lastSelectedEntryID = _activeEntry->entryID;
+ sendCommand(kItemClicked, _activeEntry->entryID);
+ return;
+ }
+
+ int32 keyState = g_system->getEventManager()->getModifierState();
+ bool ctrlPressed = (keyState & Common::KBD_CTRL) != 0;
+ bool shiftPressed = (keyState & Common::KBD_SHIFT) != 0;
+
+ if (ctrlPressed) {
+ if (_grid->isItemSelected(_activeEntry->entryID)) {
+ _grid->markSelectedItem(_activeEntry->entryID, false);
+ } else {
+ _grid->markSelectedItem(_activeEntry->entryID, true);
+ _grid->_lastSelectedEntryID = _activeEntry->entryID;
+ }
+ } else if (shiftPressed && _grid->_lastSelectedEntryID >= 0) {
+ int startID = _grid->getVisualPos(_grid->_lastSelectedEntryID);
+ int endID = _grid->getVisualPos(_activeEntry->entryID);
+ if (startID >= 0 && endID >= 0) {
+ _grid->selectVisualRange(startID, endID);
+ }
+ _grid->_lastSelectedEntryID = _activeEntry->entryID;
+ } else {
+ _grid->clearSelection();
+ _grid->markSelectedItem(_activeEntry->entryID, true);
+ _grid->_lastSelectedEntryID = _activeEntry->entryID;
+ }
+
+ sendCommand(kItemClicked, _activeEntry->entryID);
+ }
}
void GridWidget::toggleGroup(int groupID) {
@@ -257,54 +301,11 @@ void GridWidget::saveClosedGroups(const Common::U32String &groupName) {
}
void GridItemWidget::handleMouseDown(int x, int y, int button, int clickCount) {
- if (_activeEntry->isHeader) {
- _grid->_selectedEntry = nullptr;
- _grid->toggleGroup(_activeEntry->entryID);
- } else if (_isHighlighted && isVisible()) {
- _grid->_selectedEntry = _activeEntry;
-
- // If multi-select is not enabled, use simple single-selection
- if (!_grid->isMultiSelectEnabled()) {
- _grid->clearSelection();
- _grid->markSelectedItem(_activeEntry->entryID, true);
- _grid->_lastSelectedEntryID = _activeEntry->entryID;
- sendCommand(kItemClicked, _activeEntry->entryID);
- return;
- }
-
- // Get the current keyboard state
- int32 keyState = g_system->getEventManager()->getModifierState();
- bool ctrlPressed = (keyState & Common::KBD_CTRL) != 0;
- bool shiftPressed = (keyState & Common::KBD_SHIFT) != 0;
-
- if (ctrlPressed) {
- // Ctrl+Click: Toggle selection of this item
- if (_grid->isItemSelected(_activeEntry->entryID)) {
- _grid->markSelectedItem(_activeEntry->entryID, false);
- } else {
- _grid->markSelectedItem(_activeEntry->entryID, true);
- _grid->_lastSelectedEntryID = _activeEntry->entryID;
- }
- } else if (shiftPressed && _grid->_lastSelectedEntryID >= 0) {
- // Shift+Click: Select range from last selected to current item
- // Must select based on visual order, not by entryID range
- int startID = _grid->getVisualPos(_grid->_lastSelectedEntryID);
- int endID = _grid->getVisualPos(_activeEntry->entryID);
-
- // If we found both positions, select all items between them (visually)
- if (startID >= 0 && endID >= 0) {
- _grid->selectVisualRange(startID, endID);
- }
- _grid->_lastSelectedEntryID = _activeEntry->entryID;
- } else {
- // Regular click: Select only this item
- _grid->clearSelection();
- _grid->markSelectedItem(_activeEntry->entryID, true);
- _grid->_lastSelectedEntryID = _activeEntry->entryID;
- }
+ _grid->handleMouseDown(x + _x, y + _y, button, clickCount);
+}
- sendCommand(kItemClicked, _activeEntry->entryID);
- }
+void GridItemWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ _grid->handleMouseUp(x + _x, y + _y, button, clickCount);
}
#pragma mark -
@@ -514,8 +515,16 @@ GridWidget::GridWidget(GuiObject *boss, const Common::String &name)
_selectedItems.clear();
_lastSelectedEntryID = -1;
+ _isMouseDown = false;
+ _isDragging = false;
+ _selectionPending = false;
+ _dragStartY = 0;
+ _dragLastY = 0;
+
_filterMatcher = GridWidgetDefaultMatcher;
_filterMatcherArg = nullptr;
+
+ setFlags(getFlags() | WIDGET_TRACK_MOUSE);
}
GridWidget::~GridWidget() {
@@ -1001,6 +1010,53 @@ void GridWidget::handleMouseWheel(int x, int y, int direction) {
_scrollPos = _scrollBar->_currentPos;
}
+void GridWidget::handleMouseDown(int x, int y, int button, int clickCount) {
+ _isMouseDown = true;
+ _mouseDownTime = g_system->getMillis();
+ _isDragging = false;
+ _selectionPending = true;
+ _dragStartY = y;
+ _dragLastY = y;
+}
+
+void GridWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ bool wasPending = _selectionPending;
+ bool wasDragging = _isDragging;
+
+ _isMouseDown = false;
+ _isDragging = false;
+ _selectionPending = false;
+
+ if (wasPending && !wasDragging) {
+ // Find which item was clicked and select it
+ Widget *w = findWidget(x, y);
+ if (w && w != this && w->getType() == kContainerWidget)
+ ((GridItemWidget *)w)->doSelection();
+ }
+}
+
+void GridWidget::handleMouseMoved(int x, int y, int button) {
+ if (!_isMouseDown)
+ return;
+
+ if (!_isDragging && ABS(y - _dragStartY) > kDragThreshold) {
+ _isDragging = true;
+ _selectionPending = false;
+ }
+
+ if (_isDragging) {
+ int deltaY = _dragLastY - y;
+ _dragLastY = y;
+
+ int newPos = _scrollPos + deltaY;
+ int maxScroll = _scrollBar->_numEntries - _scrollBar->_entriesPerPage;
+ newPos = MAX(0, MIN(newPos, maxScroll));
+
+ if (_scrollPos != newPos)
+ handleCommand(this, kSetPositionCmd, newPos);
+ }
+}
+
bool GridWidget::handleKeyDown(Common::KeyState state) {
return false;
}
diff --git a/gui/widgets/grid.h b/gui/widgets/grid.h
index 7dd709ebdcb..a33b84e2ecb 100644
--- a/gui/widgets/grid.h
+++ b/gui/widgets/grid.h
@@ -100,6 +100,7 @@ public:
/* GridWidget */
class GridWidget : public ContainerWidget, public CommandSender {
+ friend class GridItemWidget;
public:
typedef bool (*FilterMatcher)(void *arg, int idx, const Common::U32String &item, const Common::U32String &token);
@@ -166,6 +167,14 @@ protected:
FilterMatcher _filterMatcher;
void *_filterMatcherArg;
+ // Drag to scroll
+ bool _isMouseDown;
+ bool _isDragging;
+ bool _selectionPending;
+ int _dragStartY, _dragLastY;
+ uint32 _mouseDownTime;
+ static const int kDragThreshold = 5;
+
public:
int _gridItemHeight;
int _gridItemWidth;
@@ -227,6 +236,9 @@ public:
int getThumbnailWidth() const { return _thumbnailWidth; }
void handleMouseWheel(int x, int y, int direction) override;
+ void handleMouseDown(int x, int y, int button, int clickCount) override;
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
+ void handleMouseMoved(int x, int y, int button) override;
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
void reflowLayout() override;
@@ -276,7 +288,9 @@ public:
void handleMouseEntered(int button) override;
void handleMouseLeft(int button) override;
void handleMouseDown(int x, int y, int button, int clickCount) override;
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
void handleMouseMoved(int x, int y, int button) override;
+ void doSelection();
};
} // End of namespace GUI
Commit: 15c1eaefcf750d1af9a321ac18accd0ef5a832a4
https://github.com/scummvm/scummvm/commit/15c1eaefcf750d1af9a321ac18accd0ef5a832a4
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implement Fluid scroll in Launcher Grid
Changed paths:
gui/widgets/grid.cpp
gui/widgets/grid.h
diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index fc731d7a5f4..93bdafd1bad 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -28,6 +28,7 @@
#include "gui/gui-manager.h"
#include "gui/widgets/grid.h"
+#include "gui/animation/FluidScroll.h"
#include "gui/ThemeEval.h"
@@ -490,7 +491,7 @@ GridWidget::GridWidget(GuiObject *boss, const Common::String &name)
_scrollBar = new ScrollBarWidget(this, _w - _scrollBarWidth, _y, _scrollBarWidth, _y + _h);
_scrollBar->setTarget(this);
- _scrollPos = 0;
+ _scrollPos = 0.0f;
_scrollSpeed = 1;
_firstVisibleItem = 0;
_lastVisibleItem = 0;
@@ -521,10 +522,12 @@ GridWidget::GridWidget(GuiObject *boss, const Common::String &name)
_dragStartY = 0;
_dragLastY = 0;
+ _fluidScroller = new FluidScroller();
+
_filterMatcher = GridWidgetDefaultMatcher;
_filterMatcherArg = nullptr;
- setFlags(getFlags() | WIDGET_TRACK_MOUSE);
+ setFlags(getFlags() | WIDGET_TRACK_MOUSE | WIDGET_WANT_TICKLE | WIDGET_RETAIN_FOCUS);
}
GridWidget::~GridWidget() {
@@ -541,6 +544,7 @@ GridWidget::~GridWidget() {
_platformIconsAlpha.clear();
_languageIconsAlpha.clear();
_extraIconsAlpha.clear();
+ delete _fluidScroller;
}
Common::SharedPtr<Graphics::ManagedSurface> GridWidget::filenameToSurface(const Common::String &name) {
@@ -876,7 +880,7 @@ void GridWidget::move(int x, int y) {
// Scroll to entry id. Optional parameter to decide if the entry should be forced to be on the top, or merely
// scrolled into view.
void GridWidget::scrollToEntry(int id, bool forceToTop) {
- int newScrollPos = _scrollPos;
+ float newScrollPos = _scrollPos;
for (uint i = 0; i < _sortedEntryList.size(); ++i) {
if ((!_sortedEntryList[i]->isHeader) && (_sortedEntryList[i]->entryID == id)) {
if (forceToTop) {
@@ -1006,17 +1010,24 @@ void GridWidget::selectVisualRange(int startPos, int endPos) {
}
void GridWidget::handleMouseWheel(int x, int y, int direction) {
- _scrollBar->handleMouseWheel(x, y, direction);
- _scrollPos = _scrollBar->_currentPos;
+ const float stepping = (float)_scrollBar->_singleStep * direction;
+ if (stepping == 0.0f)
+ return;
+
+ _fluidScroller->stopAnimation();
+ _fluidScroller->feedWheel(g_system->getMillis(), stepping);
}
void GridWidget::handleMouseDown(int x, int y, int button, int clickCount) {
- _isMouseDown = true;
- _mouseDownTime = g_system->getMillis();
- _isDragging = false;
+ if (button == 1) {
+ _isMouseDown = true;
+ _mouseDownTime = g_system->getMillis();
+ _isDragging = false;
+ _dragStartY = y;
+ _dragLastY = y;
+ }
_selectionPending = true;
- _dragStartY = y;
- _dragLastY = y;
+ _fluidScroller->stopAnimation();
}
void GridWidget::handleMouseUp(int x, int y, int button, int clickCount) {
@@ -1033,6 +1044,9 @@ void GridWidget::handleMouseUp(int x, int y, int button, int clickCount) {
if (w && w != this && w->getType() == kContainerWidget)
((GridItemWidget *)w)->doSelection();
}
+
+ if (wasDragging)
+ _fluidScroller->startFling();
}
void GridWidget::handleMouseMoved(int x, int y, int button) {
@@ -1048,15 +1062,28 @@ void GridWidget::handleMouseMoved(int x, int y, int button) {
int deltaY = _dragLastY - y;
_dragLastY = y;
- int newPos = _scrollPos + deltaY;
- int maxScroll = _scrollBar->_numEntries - _scrollBar->_entriesPerPage;
- newPos = MAX(0, MIN(newPos, maxScroll));
-
- if (_scrollPos != newPos)
- handleCommand(this, kSetPositionCmd, newPos);
+ if (deltaY != 0) {
+ _fluidScroller->feedDrag(g_system->getMillis(), deltaY);
+ _scrollPos = _fluidScroller->getVisualPosition();
+ applyScrollPos();
+ }
}
}
+void GridWidget::applyScrollPos() {
+ if (calcVisibleEntries())
+ reloadThumbnails();
+
+ assignEntriesToItems();
+ scrollBarRecalc();
+ g_gui.scheduleTopDialogRedraw();
+}
+
+void GridWidget::handleTickle() {
+ if (_fluidScroller->update(g_system->getMillis(), _scrollPos))
+ applyScrollPos();
+}
+
bool GridWidget::handleKeyDown(Common::KeyState state) {
return false;
}
@@ -1069,16 +1096,12 @@ void GridWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
// Work in progress
switch (cmd) {
case kSetPositionCmd:
- if (_scrollPos != (int)data) {
- _scrollPos = data;
+ if (_scrollPos != (float)data) {
+ _scrollPos = (float)data;
+ _fluidScroller->stopAnimation();
+ _scrollPos = _fluidScroller->setPosition(_scrollPos, false);
- if (calcVisibleEntries()) {
- reloadThumbnails();
- }
-
- assignEntriesToItems();
- scrollBarRecalc();
- markAsDirty();
+ applyScrollPos();
((GUI::Dialog *)_boss)->setFocusWidget(this);
}
@@ -1245,6 +1268,8 @@ void GridWidget::reflowLayout() {
scrollToEntry(_selectedEntry->entryID, false);
}
scrollBarRecalc();
+ int maxScroll = MAX(0, _scrollBar->_numEntries - _scrollBar->_entriesPerPage);
+ _fluidScroller->setBounds((float)maxScroll, _scrollBar->_entriesPerPage);
markAsDirty();
}
@@ -1262,12 +1287,13 @@ void GridWidget::openTrayAtSelected() {
void GridWidget::scrollBarRecalc() {
_scrollBar->_numEntries = _innerHeight;
_scrollBar->_entriesPerPage = _scrollWindowHeight - 2 * _scrollWindowPaddingY;
- _scrollBar->_currentPos = _scrollPos;
+ _scrollBar->_currentPos = (int)_scrollPos;
_scrollBar->_singleStep = kLineHeight;
- _scrollBar->checkBounds(_scrollBar->_currentPos);
- _scrollPos = _scrollBar->_currentPos;
_scrollBar->recalc();
+
+ int maxScroll = MAX(0, _scrollBar->_numEntries - _scrollBar->_entriesPerPage);
+ _fluidScroller->setBounds((float)maxScroll, _scrollBar->_entriesPerPage);
}
void GridWidget::setFilter(const Common::U32String &filter) {
diff --git a/gui/widgets/grid.h b/gui/widgets/grid.h
index a33b84e2ecb..20975936664 100644
--- a/gui/widgets/grid.h
+++ b/gui/widgets/grid.h
@@ -35,6 +35,7 @@ namespace GUI {
class ScrollBarWidget;
class GridItemWidget;
class GridWidget;
+class FluidScroller;
enum {
kPlayButtonCmd = 'PLAY',
@@ -137,7 +138,7 @@ protected:
int _scrollWindowHeight;
int _scrollWindowWidth;
int _scrollSpeed;
- int _scrollPos;
+ float _scrollPos;
int _innerHeight;
int _innerWidth;
int _thumbnailHeight;
@@ -175,6 +176,8 @@ protected:
uint32 _mouseDownTime;
static const int kDragThreshold = 5;
+ FluidScroller *_fluidScroller;
+
public:
int _gridItemHeight;
int _gridItemWidth;
@@ -230,7 +233,7 @@ public:
int getNewSel(int index);
int getVisualPos(int entryID) const;
void selectVisualRange(int startPos, int endPos);
- int getScrollPos() const { return _scrollPos; }
+ float getScrollPos() const { return _scrollPos; }
int getSelected() const { return ((_selectedEntry == nullptr) ? -1 : _selectedEntry->entryID); }
int getThumbnailHeight() const { return _thumbnailHeight; }
int getThumbnailWidth() const { return _thumbnailWidth; }
@@ -239,6 +242,8 @@ public:
void handleMouseDown(int x, int y, int button, int clickCount) override;
void handleMouseUp(int x, int y, int button, int clickCount) override;
void handleMouseMoved(int x, int y, int button) override;
+ void handleTickle() override;
+ void applyScrollPos(); // Updates the grid's visual elements to match current scroll position
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
void reflowLayout() override;
Commit: af56d299da48ded9e93a64b744fa1750e6fed735
https://github.com/scummvm/scummvm/commit/af56d299da48ded9e93a64b744fa1750e6fed735
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implement drag to scroll in List
Changed paths:
gui/widgets/groupedlist.cpp
gui/widgets/list.cpp
gui/widgets/list.h
diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index 00535bb2492..cca93701185 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -258,22 +258,13 @@ void GroupedListWidget::handleMouseDown(int x, int y, int button, int clickCount
if (!isEnabled())
return;
- // First check whether the selection changed
- int newSelectedItem = findItem(x, y);
- if (newSelectedItem == -1)
- return;
+ _isMouseDown = true;
+ _isDragging = false;
+ _dragLastY = 0;
- if (isGroupHeader(_listIndex[newSelectedItem])) {
- int groupID = indexToGroupID(_listIndex[newSelectedItem]);
- int oldSelection = getSelected();
- _selectedItem = -1;
- toggleGroup(groupID);
- if (oldSelection != -1) {
- _selectedItem = findDataIndex(oldSelection);
- sendCommand(kListSelectionChangedCmd, _selectedItem);
- }
- markAsDirty();
- return;
+ if (button == 1) {
+ _dragStartY = y;
+ _dragLastY = y;
}
// TODO: Determine where inside the string the user clicked and place the
@@ -281,53 +272,74 @@ void GroupedListWidget::handleMouseDown(int x, int y, int button, int clickCount
// See _editScrollOffset and EditTextWidget::handleMouseDown.
if (_editMode)
abortEditMode();
+}
- int dataIndex = _listIndex[newSelectedItem];
- if (dataIndex < 0)
- return;
-
- // Get modifier keys
- int modifiers = g_system->getEventManager()->getModifierState();
- bool ctrlClick = (modifiers & Common::KBD_CTRL) != 0;
- bool shiftClick = (modifiers & Common::KBD_SHIFT) != 0;
-
- // Only handle multi-select if it's enabled
- if (_multiSelectEnabled && (shiftClick || ctrlClick)) {
- if (shiftClick && _lastSelectionStartItem != -1) {
- // Shift+Click: Select range in terms of underlying data indices
- int startListIndex = _lastSelectionStartItem;
- int endListIndex = newSelectedItem;
- selectItemRange(startListIndex, endListIndex);
- _selectedItem = newSelectedItem;
- _lastSelectionStartItem = newSelectedItem;
- sendCommand(kListSelectionChangedCmd, _selectedItem);
- } else if (ctrlClick) {
- // Ctrl+Click: toggle selection for the underlying data index
- if (isItemSelected(newSelectedItem)) {
- markSelectedItem(newSelectedItem, false);
- } else {
- markSelectedItem(newSelectedItem, true);
- _selectedItem = newSelectedItem;
- _lastSelectionStartItem = newSelectedItem;
+void GroupedListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ if (button == 1 || button == 2) {
+ if (_isMouseDown && !_isDragging) {
+ int newSelectedItem = findItem(x, y);
+ if (newSelectedItem != -1) {
+ if (isGroupHeader(_listIndex[newSelectedItem])) {
+ int groupID = indexToGroupID(_listIndex[newSelectedItem]);
+ int oldSelection = getSelected();
+ _selectedItem = -1;
+ toggleGroup(groupID);
+ if (oldSelection != -1) {
+ _selectedItem = findDataIndex(oldSelection);
+ sendCommand(kListSelectionChangedCmd, _selectedItem);
+ }
+ applyScrollPos();
+ } else {
+ int dataIndex = _listIndex[newSelectedItem];
+ if (dataIndex >= 0) {
+ // Get modifier keys
+ int modifiers = g_system->getEventManager()->getModifierState();
+ bool ctrlClick = (modifiers & Common::KBD_CTRL) != 0;
+ bool shiftClick = (modifiers & Common::KBD_SHIFT) != 0;
+
+ // Only handle multi-select if it's enabled
+ if (_multiSelectEnabled && (shiftClick || ctrlClick)) {
+ if (shiftClick && _lastSelectionStartItem != -1) {
+ // Shift+Click: Select range in terms of underlying data indices
+ int startListIndex = _lastSelectionStartItem;
+ int endListIndex = newSelectedItem;
+ selectItemRange(startListIndex, endListIndex);
+ _selectedItem = newSelectedItem;
+ _lastSelectionStartItem = newSelectedItem;
+ sendCommand(kListSelectionChangedCmd, _selectedItem);
+ } else if (ctrlClick) {
+ // Ctrl+Click: toggle selection for the underlying data index
+ if (isItemSelected(newSelectedItem)) {
+ markSelectedItem(newSelectedItem, false);
+ } else {
+ markSelectedItem(newSelectedItem, true);
+ _selectedItem = newSelectedItem;
+ _lastSelectionStartItem = newSelectedItem;
+ }
+ sendCommand(kListSelectionChangedCmd, _selectedItem);
+ }
+ } else {
+ // Regular click: clear selection and select only this underlying item
+ clearSelection();
+ _selectedItem = newSelectedItem;
+ markSelectedItem(newSelectedItem, true);
+ sendCommand(kListSelectionChangedCmd, _selectedItem);
+ }
+
+ // Notify clients if an item was clicked
+ if (newSelectedItem >= 0)
+ sendCommand(kListItemSingleClickedCmd, _selectedItem);
+
+ applyScrollPos();
+ }
+ }
}
- sendCommand(kListSelectionChangedCmd, _selectedItem);
}
- } else {
- // Regular click: clear selection and select only this underlying item
- clearSelection();
- _selectedItem = newSelectedItem;
- markSelectedItem(newSelectedItem, true);
- sendCommand(kListSelectionChangedCmd, _selectedItem);
- }
-
- // Notify clients if an item was clicked
- if (newSelectedItem >= 0)
- sendCommand(kListItemSingleClickedCmd, _selectedItem);
- markAsDirty();
-}
+ _isMouseDown = false;
+ _isDragging = false;
+ }
-void GroupedListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
// If this was a double click and the mouse is still over
// the selected item, send the double click command
if (clickCount == 2 && (_selectedItem == findItem(x, y))) {
@@ -346,9 +358,8 @@ void GroupedListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32
switch (cmd) {
case kSetPositionCmd:
if (_currentPos != (int)data) {
- _currentPos = data;
- checkBounds();
- markAsDirty();
+ _scrollPos = (float)data * (kLineHeight + _itemSpacing);
+ applyScrollPos();
// Scrollbar actions cause list focus (which triggers a redraw)
// NOTE: ListWidget's boss is always GUI::Dialog
@@ -412,9 +423,15 @@ void GroupedListWidget::drawWidget() {
// Draw the list items
const int lineHeight = kLineHeight + _itemSpacing;
+ const int firstItem = (int)(_scrollPos / lineHeight);
+ const int offset = (int)_scrollPos % lineHeight;
const int indentSpacing = g_gui.getFontHeight();
- for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) {
- const int y = _y + _topPadding + lineHeight * i;
+
+ Common::Rect innerRect(_x, _y + _topPadding, _x + _w - _scrollBarWidth, _y + _h - _bottomPadding);
+ Common::Rect oldClip = g_gui.theme()->swapClipRect(innerRect.findIntersectingRect(g_gui.theme()->getClipRect()));
+
+ for (i = 0, pos = firstItem; i <= _entriesPerPage && pos < len; i++, pos++) {
+ const int y = _y + _topPadding + lineHeight * i - offset;
ThemeEngine::TextInversionState inverted = ThemeEngine::kTextInversionNone;
#if 0
ThemeEngine::FontStyle bold = ThemeEngine::kFontStyleBold;
@@ -492,6 +509,9 @@ void GroupedListWidget::drawWidget() {
g_gui.theme()->drawText(r2, buffer, itemState, _drawAlign, inverted, _leftPadding, true);
}
}
+
+ g_gui.theme()->swapClipRect(oldClip);
+
if (_editMode)
EditableWidget::drawWidget();
}
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index b9362f7059a..8d94ffe7ae9 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -79,6 +79,11 @@ ListWidget::ListWidget(Dialog *boss, const Common::String &name, const Common::U
_leftPadding = _rightPadding = 0;
_topPadding = _bottomPadding = 0;
_itemSpacing = 0;
+
+ _scrollPos = 0.0f;
+ _isMouseDown = false;
+ _isDragging = false;
+ _dragStartY = _dragLastY = 0;
}
ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, bool scale, const Common::U32String &tooltip, uint32 cmd)
@@ -90,7 +95,7 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, bool scale, con
_scrollBar = new ScrollBarWidget(this, _w - _scrollBarWidth, 0, _scrollBarWidth, _h);
_scrollBar->setTarget(this);
- setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE);
+ setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE | WIDGET_TRACK_MOUSE);
_type = kListWidget;
_editMode = false;
_numberingMode = kListNumberingOne;
@@ -126,6 +131,11 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, bool scale, con
_itemSpacing = 0;
_scrollBarWidth = 0;
+
+ _scrollPos = 0.0f;
+ _isMouseDown = false;
+ _isDragging = false;
+ _dragStartY = _dragLastY = 0;
}
ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const Common::U32String &tooltip, uint32 cmd)
@@ -339,63 +349,90 @@ void ListWidget::handleTickle() {
_scrollBar->handleTickle();
}
+void ListWidget::applyScrollPos() {
+ const int lineHeight = kLineHeight + _itemSpacing;
+ int maxScroll = MAX(0, (int)(_scrollBar->_numEntries - _scrollBar->_entriesPerPage) * lineHeight);
+ if (_scrollPos < 0)
+ _scrollPos = 0;
+ if (_scrollPos > maxScroll)
+ _scrollPos = (float)maxScroll;
+
+ _currentPos = (int)(_scrollPos / lineHeight);
+ scrollBarRecalc();
+ markAsDirty();
+}
+
void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
if (!isEnabled())
return;
- // First check whether the selection changed
- int newSelectedItem = findItem(x, y);
+ _isMouseDown = true;
+ _isDragging = false;
+ _dragLastY = 0;
- if (newSelectedItem == -1)
- return;
+ if (button == 1) {
+ _dragStartY = y;
+ _dragLastY = y;
+ }
if (_editMode)
abortEditMode();
+}
- // Get modifier keys
- int modifiers = g_system->getEventManager()->getModifierState();
- bool ctrlClick = (modifiers & Common::KBD_CTRL) != 0;
- bool shiftClick = (modifiers & Common::KBD_SHIFT) != 0;
-
- // Only handle multi-select if it's enabled
- if (_multiSelectEnabled && (shiftClick || ctrlClick)) {
- if (shiftClick && _lastSelectionStartItem != -1) {
- // Shift+Click: Select range from last selection start to current item
- _selectedItem = newSelectedItem;
- selectItemRange(_lastSelectionStartItem, newSelectedItem);
- _lastSelectionStartItem = newSelectedItem;
- sendCommand(kListSelectionChangedCmd, _selectedItem);
- } else if (ctrlClick) {
- // Ctrl+Click: Add/remove from selection
- if (isItemSelected(newSelectedItem)) {
- markSelectedItem(newSelectedItem, false);
- } else {
- markSelectedItem(newSelectedItem, true);
- _selectedItem = newSelectedItem;
- _lastSelectionStartItem = newSelectedItem;
- }
- sendCommand(kListSelectionChangedCmd, _selectedItem);
- }
- } else {
- // Regular click: Clear previous selection and select only this item
- clearSelection();
- _selectedItem = newSelectedItem;
- markSelectedItem(newSelectedItem, true);
- sendCommand(kListSelectionChangedCmd, _selectedItem);
- }
+void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ if (button == 1 || button == 2) {
+ if (_isMouseDown && !_isDragging) {
+ // Perform selection
+ int newSelectedItem = findItem(x, y);
+ if (newSelectedItem != -1) {
+ // Get modifier keys
+ int modifiers = g_system->getEventManager()->getModifierState();
+ bool ctrlClick = (modifiers & Common::KBD_CTRL) != 0;
+ bool shiftClick = (modifiers & Common::KBD_SHIFT) != 0;
+
+ // Only handle multi-select if it's enabled
+ if (_multiSelectEnabled && (shiftClick || ctrlClick)) {
+ if (shiftClick && _lastSelectionStartItem != -1) {
+ // Shift+Click: Select range from last selection start to current item
+ _selectedItem = newSelectedItem;
+ selectItemRange(_lastSelectionStartItem, newSelectedItem);
+ _lastSelectionStartItem = newSelectedItem;
+ sendCommand(kListSelectionChangedCmd, _selectedItem);
+ } else if (ctrlClick) {
+ // Ctrl+Click: Add/remove from selection
+ if (isItemSelected(newSelectedItem)) {
+ markSelectedItem(newSelectedItem, false);
+ } else {
+ markSelectedItem(newSelectedItem, true);
+ _selectedItem = newSelectedItem;
+ _lastSelectionStartItem = newSelectedItem;
+ }
+ sendCommand(kListSelectionChangedCmd, _selectedItem);
+ }
+ } else {
+ // Regular click: Clear previous selection and select only this item
+ clearSelection();
+ _selectedItem = newSelectedItem;
+ markSelectedItem(newSelectedItem, true);
+ sendCommand(kListSelectionChangedCmd, _selectedItem);
+ }
- // Notify clients if an item was clicked
- if (newSelectedItem >= 0) {
- sendCommand(kListItemSingleClickedCmd, _selectedItem);
- }
+ // Notify clients if an item was clicked
+ if (newSelectedItem >= 0) {
+ sendCommand(kListItemSingleClickedCmd, _selectedItem);
+ }
// TODO: Determine where inside the string the user clicked and place the
// caret accordingly.
// See _editScrollOffset and EditTextWidget::handleMouseDown.
- markAsDirty();
-}
+ markAsDirty();
+ }
+ }
+
+ _isMouseDown = false;
+ _isDragging = false;
+ }
-void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
// If this was a double click and the mouse is still over
// the selected item, send the double click command
if (clickCount == 2 && (_selectedItem == findItem(x, y)) &&
@@ -412,6 +449,22 @@ void ListWidget::handleMouseMoved(int x, int y, int button) {
if (!isEnabled())
return;
+ if (_isMouseDown && _dragLastY != 0) {
+ if (!_isDragging && ABS(y - _dragStartY) > kDragThreshold)
+ _isDragging = true;
+
+ if (_isDragging) {
+ int deltaY = _dragLastY - y;
+ _dragLastY = y;
+
+ if (deltaY != 0) {
+ _scrollPos += deltaY;
+ applyScrollPos();
+ }
+ return;
+ }
+ }
+
// Determine if we are inside the widget
if (x < 0 || x > _w)
return;
@@ -435,9 +488,12 @@ void ListWidget::handleMouseLeft(int button) {
int ListWidget::findItem(int x, int y) const {
- if (y < _topPadding) return -1;
- int item = (y - _topPadding) / (kLineHeight + _itemSpacing) + _currentPos;
- if (isItemVisible(item) && item < (int)_list.size())
+ if (y < _topPadding || y >= _h - _bottomPadding)
+ return -1;
+
+ int item = (y - _topPadding + (int)_scrollPos) / (kLineHeight + _itemSpacing);
+
+ if (item >= 0 && item < (int)_list.size())
return item;
else
return -1;
@@ -764,9 +820,8 @@ void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kSetPositionCmd:
if (_currentPos != (int)data) {
- _currentPos = data;
- checkBounds();
- markAsDirty();
+ _scrollPos = (float)data * (kLineHeight + _itemSpacing);
+ applyScrollPos();
// Scrollbar actions cause list focus (which triggers a redraw)
// NOTE: ListWidget's boss is always GUI::Dialog
@@ -788,8 +843,14 @@ void ListWidget::drawWidget() {
// Draw the list items
const int lineHeight = kLineHeight + _itemSpacing;
- for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) {
- const int y = _y + _topPadding + lineHeight * i;
+ const int firstItem = (int)(_scrollPos / lineHeight);
+ const int offset = (int)_scrollPos % lineHeight;
+
+ Common::Rect innerRect(_x, _y + _topPadding, _x + _w - _scrollBarWidth, _y + _h - _bottomPadding);
+ Common::Rect oldClip = g_gui.theme()->swapClipRect(innerRect.findIntersectingRect(g_gui.theme()->getClipRect()));
+
+ for (i = 0, pos = firstItem; i <= _entriesPerPage && pos < len; i++, pos++) {
+ const int y = _y + _topPadding + lineHeight * i - offset;
ThemeEngine::TextInversionState inverted = ThemeEngine::kTextInversionNone;
// Draw the selected item inverted, on a highlighted background.
@@ -848,6 +909,8 @@ void ListWidget::drawWidget() {
}
}
+ g_gui.theme()->swapClipRect(oldClip);
+
if (_editMode) {
EditableWidget::drawWidget();
}
diff --git a/gui/widgets/list.h b/gui/widgets/list.h
index f99b2574465..2e271582a62 100644
--- a/gui/widgets/list.h
+++ b/gui/widgets/list.h
@@ -77,6 +77,12 @@ protected:
ScrollBarWidget *_scrollBar;
int _currentKeyDown;
+ float _scrollPos;
+ bool _isMouseDown;
+ bool _isDragging;
+ int _dragStartY;
+ int _dragLastY;
+
Common::String _quickSelectStr;
uint32 _quickSelectTime;
@@ -101,6 +107,9 @@ protected:
FilterMatcher _filterMatcher;
void *_filterMatcherArg;
+
+ static const int kDragThreshold = 5;
+
public:
ListWidget(Dialog *boss, const Common::String &name, const Common::U32String &tooltip = Common::U32String(), uint32 cmd = 0);
ListWidget(Dialog *boss, int x, int y, int w, int h, bool scale, const Common::U32String &tooltip = Common::U32String(), uint32 cmd = 0);
@@ -157,6 +166,7 @@ public:
void setFilter(const Common::U32String &filter, bool redraw = true);
void handleTickle() override;
+ void applyScrollPos();
void handleMouseDown(int x, int y, int button, int clickCount) override;
void handleMouseUp(int x, int y, int button, int clickCount) override;
void handleMouseWheel(int x, int y, int direction) override;
Commit: cb71d7b6cf946945add11834a6d957726d27dbc3
https://github.com/scummvm/scummvm/commit/cb71d7b6cf946945add11834a6d957726d27dbc3
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implement Fluid scroll in Launcher List
Changed paths:
gui/widgets/groupedlist.cpp
gui/widgets/list.cpp
gui/widgets/list.h
diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index cca93701185..45b12838f6a 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -29,6 +29,7 @@
#include "gui/widgets/scrollbar.h"
#include "gui/dialog.h"
#include "gui/gui-manager.h"
+#include "gui/animation/FluidScroll.h"
#include "gui/ThemeEval.h"
@@ -265,6 +266,7 @@ void GroupedListWidget::handleMouseDown(int x, int y, int button, int clickCount
if (button == 1) {
_dragStartY = y;
_dragLastY = y;
+ _fluidScroller->stopAnimation();
}
// TODO: Determine where inside the string the user clicked and place the
@@ -276,6 +278,9 @@ void GroupedListWidget::handleMouseDown(int x, int y, int button, int clickCount
void GroupedListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
if (button == 1 || button == 2) {
+ if (_isMouseDown && button == 1 && _isDragging)
+ _fluidScroller->startFling();
+
if (_isMouseDown && !_isDragging) {
int newSelectedItem = findItem(x, y);
if (newSelectedItem != -1) {
@@ -351,7 +356,13 @@ void GroupedListWidget::handleMouseUp(int x, int y, int button, int clickCount)
}
void GroupedListWidget::handleMouseWheel(int x, int y, int direction) {
- _scrollBar->handleMouseWheel(x, y, direction);
+ const float stepping = (float)_scrollBar->_singleStep * direction;
+
+ if (stepping == 0.0f)
+ return;
+
+ _fluidScroller->stopAnimation();
+ _fluidScroller->feedWheel(g_system->getMillis(), stepping);
}
void GroupedListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
@@ -359,6 +370,8 @@ void GroupedListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32
case kSetPositionCmd:
if (_currentPos != (int)data) {
_scrollPos = (float)data * (kLineHeight + _itemSpacing);
+ _fluidScroller->stopAnimation();
+ _scrollPos = _fluidScroller->setPosition(_scrollPos, false);
applyScrollPos();
// Scrollbar actions cause list focus (which triggers a redraw)
@@ -423,8 +436,8 @@ void GroupedListWidget::drawWidget() {
// Draw the list items
const int lineHeight = kLineHeight + _itemSpacing;
- const int firstItem = (int)(_scrollPos / lineHeight);
- const int offset = (int)_scrollPos % lineHeight;
+ const int firstItem = MAX(0, (int)(_scrollPos / lineHeight));
+ const int offset = _scrollPos < 0 ? (int)_scrollPos : (int)_scrollPos % lineHeight;
const int indentSpacing = g_gui.getFontHeight();
Common::Rect innerRect(_x, _y + _topPadding, _x + _w - _scrollBarWidth, _y + _h - _bottomPadding);
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index 8d94ffe7ae9..b7761d0d31f 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -27,6 +27,7 @@
#include "gui/widgets/scrollbar.h"
#include "gui/dialog.h"
#include "gui/gui-manager.h"
+#include "gui/animation/FluidScroll.h"
#include "gui/ThemeEval.h"
@@ -81,6 +82,7 @@ ListWidget::ListWidget(Dialog *boss, const Common::String &name, const Common::U
_itemSpacing = 0;
_scrollPos = 0.0f;
+ _fluidScroller = new FluidScroller();
_isMouseDown = false;
_isDragging = false;
_dragStartY = _dragLastY = 0;
@@ -133,11 +135,16 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, bool scale, con
_scrollBarWidth = 0;
_scrollPos = 0.0f;
+ _fluidScroller = new FluidScroller();
_isMouseDown = false;
_isDragging = false;
_dragStartY = _dragLastY = 0;
}
+ListWidget::~ListWidget() {
+ delete _fluidScroller;
+}
+
ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const Common::U32String &tooltip, uint32 cmd)
: ListWidget(boss, x, y, w, h, false, tooltip, cmd) {
}
@@ -337,29 +344,32 @@ void ListWidget::scrollTo(int item) {
}
void ListWidget::scrollBarRecalc() {
+ const int lineHeight = kLineHeight + _itemSpacing;
_scrollBar->_numEntries = _list.size();
_scrollBar->_entriesPerPage = _entriesPerPage;
_scrollBar->_currentPos = _currentPos;
+ _scrollBar->_singleStep = lineHeight;
_scrollBar->recalc();
+
+ int maxScroll = MAX(0, (int)(_scrollBar->_numEntries - _scrollBar->_entriesPerPage) * lineHeight);
+ _fluidScroller->setBounds((float)maxScroll, _h - _topPadding - _bottomPadding);
}
void ListWidget::handleTickle() {
if (_editMode)
EditableWidget::handleTickle();
_scrollBar->handleTickle();
+
+ if (_fluidScroller->update(g_system->getMillis(), _scrollPos)) {
+ applyScrollPos();
+ }
}
void ListWidget::applyScrollPos() {
const int lineHeight = kLineHeight + _itemSpacing;
- int maxScroll = MAX(0, (int)(_scrollBar->_numEntries - _scrollBar->_entriesPerPage) * lineHeight);
- if (_scrollPos < 0)
- _scrollPos = 0;
- if (_scrollPos > maxScroll)
- _scrollPos = (float)maxScroll;
-
_currentPos = (int)(_scrollPos / lineHeight);
scrollBarRecalc();
- markAsDirty();
+ g_gui.scheduleTopDialogRedraw();
}
void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
@@ -369,6 +379,7 @@ void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
_isMouseDown = true;
_isDragging = false;
_dragLastY = 0;
+ _fluidScroller->stopAnimation();
if (button == 1) {
_dragStartY = y;
@@ -381,6 +392,9 @@ void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
if (button == 1 || button == 2) {
+ if (_isMouseDown && button == 1 && _isDragging)
+ _fluidScroller->startFling();
+
if (_isMouseDown && !_isDragging) {
// Perform selection
int newSelectedItem = findItem(x, y);
@@ -442,7 +456,13 @@ void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
}
void ListWidget::handleMouseWheel(int x, int y, int direction) {
- _scrollBar->handleMouseWheel(x, y, direction);
+ const float stepping = (float)_scrollBar->_singleStep * direction;
+
+ if (stepping == 0.0f)
+ return;
+
+ _fluidScroller->stopAnimation();
+ _fluidScroller->feedWheel(g_system->getMillis(), stepping);
}
void ListWidget::handleMouseMoved(int x, int y, int button) {
@@ -458,7 +478,9 @@ void ListWidget::handleMouseMoved(int x, int y, int button) {
_dragLastY = y;
if (deltaY != 0) {
- _scrollPos += deltaY;
+ _fluidScroller->feedDrag(g_system->getMillis(), deltaY);
+ _scrollPos = _fluidScroller->getVisualPosition();
+
applyScrollPos();
}
return;
@@ -821,6 +843,8 @@ void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
case kSetPositionCmd:
if (_currentPos != (int)data) {
_scrollPos = (float)data * (kLineHeight + _itemSpacing);
+ _fluidScroller->stopAnimation();
+ _scrollPos = _fluidScroller->setPosition(_scrollPos, false);
applyScrollPos();
// Scrollbar actions cause list focus (which triggers a redraw)
@@ -843,8 +867,8 @@ void ListWidget::drawWidget() {
// Draw the list items
const int lineHeight = kLineHeight + _itemSpacing;
- const int firstItem = (int)(_scrollPos / lineHeight);
- const int offset = (int)_scrollPos % lineHeight;
+ const int firstItem = MAX(0, (int)(_scrollPos / lineHeight));
+ const int offset = _scrollPos < 0 ? (int)_scrollPos : (int)_scrollPos % lineHeight;
Common::Rect innerRect(_x, _y + _topPadding, _x + _w - _scrollBarWidth, _y + _h - _bottomPadding);
Common::Rect oldClip = g_gui.theme()->swapClipRect(innerRect.findIntersectingRect(g_gui.theme()->getClipRect()));
diff --git a/gui/widgets/list.h b/gui/widgets/list.h
index 2e271582a62..c0196d58d44 100644
--- a/gui/widgets/list.h
+++ b/gui/widgets/list.h
@@ -30,6 +30,7 @@
namespace GUI {
class ScrollBarWidget;
+class FluidScroller;
enum NumberingMode {
kListNumberingOff = -1,
@@ -60,6 +61,7 @@ public:
};
typedef Common::Array<ListData> ListDataArray;
+ ~ListWidget() override;
protected:
Common::U32StringArray _list;
@@ -78,6 +80,7 @@ protected:
int _currentKeyDown;
float _scrollPos;
+ FluidScroller *_fluidScroller;
bool _isMouseDown;
bool _isDragging;
int _dragStartY;
Commit: a2abc4c1e516f5b3ba5755eac825717b40349e0f
https://github.com/scummvm/scummvm/commit/a2abc4c1e516f5b3ba5755eac825717b40349e0f
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Centralize mouse wheel handling in FluidScroller
Changed paths:
gui/about.cpp
gui/animation/FluidScroll.cpp
gui/animation/FluidScroll.h
gui/widgets/grid.cpp
gui/widgets/groupedlist.cpp
gui/widgets/list.cpp
diff --git a/gui/about.cpp b/gui/about.cpp
index c7968731761..c7659ec9122 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -436,21 +436,8 @@ void AboutDialog::handleMouseMoved(int x, int y, int button) {
}
void AboutDialog::handleMouseWheel(int x, int y, int direction) {
- const int stepping = 5 * _lineHeight * direction;
-
- if (stepping == 0)
- return;
-
_autoScroll = false;
- _fluidScroller->stopAnimation();
- _fluidScroller->feedWheel(g_system->getMillis(), (float)stepping);
-
- if (_scrollbar) {
- _scrollbar->_currentPos = (int)_fluidScroller->getVisualPosition();
- _scrollbar->recalc();
- }
-
- drawDialog(kDrawLayerForeground);
+ _fluidScroller->handleMouseWheel(direction, (float)_lineHeight);
}
void AboutDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
diff --git a/gui/animation/FluidScroll.cpp b/gui/animation/FluidScroll.cpp
index d714f7d0d0b..830f31bd269 100644
--- a/gui/animation/FluidScroll.cpp
+++ b/gui/animation/FluidScroll.cpp
@@ -169,6 +169,15 @@ void FluidScroller::feedWheel(uint32 time, float deltaY) {
startFling(velocity);
}
+void FluidScroller::handleMouseWheel(int direction, float stepSize, float multiplier) {
+ float stepping = stepSize * (float)direction * multiplier;
+ if (stepping == 0.0f)
+ return;
+
+ stopAnimation();
+ feedWheel(g_system->getMillis(), stepping);
+}
+
void FluidScroller::absorb(float velocity, float distance) {
_mode = kModeSpringBack;
_startTime = g_system->getMillis();
diff --git a/gui/animation/FluidScroll.h b/gui/animation/FluidScroll.h
index 15e14f06ed1..4c2114a6b21 100644
--- a/gui/animation/FluidScroll.h
+++ b/gui/animation/FluidScroll.h
@@ -64,6 +64,14 @@ public:
// Record a wheel tick and start/update a fling
void feedWheel(uint32 time, float deltaY);
+ /**
+ * Handle mouse wheel input
+ * @param direction Scroll direction
+ * @param stepSize usually _scrollBar->_singleStep
+ * @param multiplier Speed multiplier for the scroll
+ */
+ void handleMouseWheel(int direction, float stepSize, float multiplier = 1.0f);
+
// Check if there is an active animation (fling or spring-back)
bool isAnimating() const { return _mode != kModeNone; }
diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index 93bdafd1bad..0132e4060be 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -901,6 +901,8 @@ void GridWidget::scrollToEntry(int id, bool forceToTop) {
}
}
handleCommand(this, kSetPositionCmd, newScrollPos);
+ _scrollPos = newScrollPos;
+ applyScrollPos();
}
void GridWidget::updateGrid() {
@@ -1010,12 +1012,7 @@ void GridWidget::selectVisualRange(int startPos, int endPos) {
}
void GridWidget::handleMouseWheel(int x, int y, int direction) {
- const float stepping = (float)_scrollBar->_singleStep * direction;
- if (stepping == 0.0f)
- return;
-
- _fluidScroller->stopAnimation();
- _fluidScroller->feedWheel(g_system->getMillis(), stepping);
+ _fluidScroller->handleMouseWheel(direction, (float)_scrollBar->_singleStep);
}
void GridWidget::handleMouseDown(int x, int y, int button, int clickCount) {
@@ -1287,12 +1284,13 @@ void GridWidget::openTrayAtSelected() {
void GridWidget::scrollBarRecalc() {
_scrollBar->_numEntries = _innerHeight;
_scrollBar->_entriesPerPage = _scrollWindowHeight - 2 * _scrollWindowPaddingY;
- _scrollBar->_currentPos = (int)_scrollPos;
+ int maxScroll = MAX(0, _scrollBar->_numEntries - _scrollBar->_entriesPerPage);
+ _scrollBar->_currentPos = CLIP<int>((int)_scrollPos, 0, maxScroll);
_scrollBar->_singleStep = kLineHeight;
_scrollBar->recalc();
- int maxScroll = MAX(0, _scrollBar->_numEntries - _scrollBar->_entriesPerPage);
+ maxScroll = MAX(0, _scrollBar->_numEntries - _scrollBar->_entriesPerPage);
_fluidScroller->setBounds((float)maxScroll, _scrollBar->_entriesPerPage);
}
diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index 45b12838f6a..cd5cf359aad 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -356,13 +356,7 @@ void GroupedListWidget::handleMouseUp(int x, int y, int button, int clickCount)
}
void GroupedListWidget::handleMouseWheel(int x, int y, int direction) {
- const float stepping = (float)_scrollBar->_singleStep * direction;
-
- if (stepping == 0.0f)
- return;
-
- _fluidScroller->stopAnimation();
- _fluidScroller->feedWheel(g_system->getMillis(), stepping);
+ _fluidScroller->handleMouseWheel(direction, (float)_scrollBar->_singleStep);
}
void GroupedListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index b7761d0d31f..5f75f3a5cbd 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -337,6 +337,8 @@ void ListWidget::scrollTo(int item) {
if (_currentPos != item) {
_currentPos = item;
+ _scrollPos = (float)_currentPos * (kLineHeight + _itemSpacing);
+ _fluidScroller->setPosition(_scrollPos, false);
checkBounds();
scrollBarRecalc();
markAsDirty();
@@ -347,7 +349,8 @@ void ListWidget::scrollBarRecalc() {
const int lineHeight = kLineHeight + _itemSpacing;
_scrollBar->_numEntries = _list.size();
_scrollBar->_entriesPerPage = _entriesPerPage;
- _scrollBar->_currentPos = _currentPos;
+ int maxIndex = MAX(0, (int)_list.size() - _entriesPerPage);
+ _scrollBar->_currentPos = CLIP<int>(_currentPos, 0, maxIndex);
_scrollBar->_singleStep = lineHeight;
_scrollBar->recalc();
@@ -456,13 +459,7 @@ void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
}
void ListWidget::handleMouseWheel(int x, int y, int direction) {
- const float stepping = (float)_scrollBar->_singleStep * direction;
-
- if (stepping == 0.0f)
- return;
-
- _fluidScroller->stopAnimation();
- _fluidScroller->feedWheel(g_system->getMillis(), stepping);
+ _fluidScroller->handleMouseWheel(direction, (float)_scrollBar->_singleStep);
}
void ListWidget::handleMouseMoved(int x, int y, int button) {
@@ -994,8 +991,10 @@ void ListWidget::scrollToCurrent() {
}
checkBounds();
+ _scrollPos = (float)_currentPos * (kLineHeight + _itemSpacing);
_scrollBar->_currentPos = _currentPos;
_scrollBar->recalc();
+ _fluidScroller->setPosition(_scrollPos, false);
}
void ListWidget::scrollToEnd() {
Commit: 5ef242d11273bf643db3bc5de70d78b426efb7af
https://github.com/scummvm/scummvm/commit/5ef242d11273bf643db3bc5de70d78b426efb7af
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implenet Fluid Scroll in Richtext widget
- Implement Fluid Scroll in HelpDialog
Changed paths:
gui/helpdialog.cpp
gui/helpdialog.h
gui/widgets/richtext.cpp
gui/widgets/richtext.h
gui/widgets/tab.cpp
gui/widgets/tab.h
diff --git a/gui/helpdialog.cpp b/gui/helpdialog.cpp
index 07ce8b2b973..635d3c8c598 100644
--- a/gui/helpdialog.cpp
+++ b/gui/helpdialog.cpp
@@ -156,4 +156,8 @@ void HelpDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
}
}
+void HelpDialog::handleTickle() {
+ _tab->handleTickle();
+}
+
} // End of namespace GUI
diff --git a/gui/helpdialog.h b/gui/helpdialog.h
index 59ed5208ffb..3e8b0a34ff3 100644
--- a/gui/helpdialog.h
+++ b/gui/helpdialog.h
@@ -39,6 +39,7 @@ public:
HelpDialog();
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
+ void handleTickle() override;
private:
void addTabs(const char * const *tabs);
diff --git a/gui/widgets/richtext.cpp b/gui/widgets/richtext.cpp
index dc78201fb92..a63a254bbb9 100644
--- a/gui/widgets/richtext.cpp
+++ b/gui/widgets/richtext.cpp
@@ -33,6 +33,7 @@
#include "gui/widgets/richtext.h"
#include "gui/widgets/scrollbar.h"
+#include "gui/animation/FluidScroll.h"
namespace GUI {
@@ -65,7 +66,7 @@ RichTextWidget::RichTextWidget(GuiObject *boss, const Common::String &name, cons
}
void RichTextWidget::init() {
- setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_TRACK_MOUSE | WIDGET_DYN_TOOLTIP);
+ setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_TRACK_MOUSE | WIDGET_DYN_TOOLTIP | WIDGET_WANT_TICKLE | WIDGET_RETAIN_FOCUS);
_type = kRichTextWidget;
@@ -81,6 +82,10 @@ void RichTextWidget::init() {
_textHeight = MAX(1, _h - 2 * _innerMargin);
_limitH = 140;
+
+ _scrollPos = 0.0f;
+ _fluidScroller = new FluidScroller();
+ _isDragging = false;
}
@@ -94,25 +99,33 @@ RichTextWidget::~RichTextWidget() {
if (_cachedTextSurface)
_cachedTextSurface->free();
delete _cachedTextSurface;
+ delete _fluidScroller;
}
void RichTextWidget::handleMouseWheel(int x, int y, int direction) {
- _verticalScroll->handleMouseWheel(x, y, direction);
+ _fluidScroller->handleMouseWheel(direction, (float)_verticalScroll->_singleStep);
+ applyScrollPos();
}
void RichTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
_mouseDownY = _mouseDownStartY = y;
+ _fluidScroller->stopAnimation();
}
void RichTextWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ if (_isDragging)
+ _fluidScroller->startFling();
+
// Allow some tiny finger slipping
- if (ABS(_mouseDownY - _mouseDownStartY) > 5) {
+ if (ABS(_mouseDownY - _mouseDownStartY) > 5 || _isDragging) {
_mouseDownY = _mouseDownStartY = 0;
+ _isDragging = false;
return;
}
_mouseDownY = _mouseDownStartY = 0;
+ _isDragging = false;
if (!_txtWnd)
return;
@@ -136,23 +149,31 @@ void RichTextWidget::handleMouseMoved(int x, int y, int button) {
if (_mouseDownStartY == 0 || _mouseDownY == y || !_txtWnd)
return;
- int h = _txtWnd->getTextHeight();
- int prevScrolledY = _scrolledY;
+ int deltaY = _mouseDownY - y;
- _scrolledY = CLIP(_scrolledY - (y - _mouseDownY), 0, h);
+ if (!_isDragging && ABS(deltaY) > 5)
+ _isDragging = true;
- _mouseDownY = y;
+ if (_isDragging) {
+ _mouseDownY = y;
+ if (deltaY != 0) {
+ _fluidScroller->feedDrag(g_system->getMillis(), deltaY);
+ applyScrollPos();
+ }
+ }
+}
- if (_scrolledY == prevScrolledY)
- return;
+void RichTextWidget::handleTickle() {
+ if (_fluidScroller->update(g_system->getMillis(), _scrollPos))
+ applyScrollPos();
+}
- recalc();
+void RichTextWidget::applyScrollPos() {
+ _scrollPos = _fluidScroller->getVisualPosition();
+ _scrolledY = (int)_scrollPos;
+ int maxScroll = MAX(0, _txtWnd->getTextHeight() - _limitH);
+ _verticalScroll->_currentPos = CLIP((int)_scrolledY, 0, (int)maxScroll);
_verticalScroll->recalc();
-
- // Update scrollbar position
- _verticalScroll->_currentPos = _scrolledY;
- _verticalScroll->checkBounds(_verticalScroll->_currentPos);
-
markAsDirty();
}
@@ -168,6 +189,9 @@ void RichTextWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
switch (cmd) {
case kSetPositionCmd:
_scrolledY = _verticalScroll->_currentPos;
+ _scrollPos = _scrolledY;
+ _fluidScroller->stopAnimation();
+ _scrollPos = _fluidScroller->setPosition(_scrollPos, false);
reflowLayout();
g_gui.scheduleTopDialogRedraw();
break;
@@ -212,18 +236,16 @@ void RichTextWidget::recalc() {
_surface->create(_textWidth, _textHeight, g_gui.getWM()->_pixelformat);
int h = _txtWnd->getTextHeight();
- if (h <= _limitH)
- _scrolledY = 0;
- if (_scrolledY > h - _limitH)
- _scrolledY = MAX(0, h - _limitH);
+ int maxScroll = MAX(0, h - _limitH);
_verticalScroll->_numEntries = h;
- _verticalScroll->_currentPos = _scrolledY;
+ _verticalScroll->_currentPos = CLIP((int)_scrolledY, 0, (int)maxScroll);
_verticalScroll->_entriesPerPage = _limitH;
_verticalScroll->_singleStep = _h / 4;
_verticalScroll->setPos(_w - _scrollbarWidth, 0);
_verticalScroll->setSize(_scrollbarWidth, _h - 1);
_verticalScroll->setVisible(_verticalScroll->_numEntries > _limitH); //show when there is something to scroll
_verticalScroll->recalc();
+ _fluidScroller->setBounds((float)maxScroll, (float)_limitH);
}
}
@@ -297,18 +319,16 @@ void RichTextWidget::createWidget() {
}
int h = _txtWnd->getTextHeight();
- if (h <= _limitH)
- _scrolledY = 0;
- if (_scrolledY > h - _limitH)
- _scrolledY = MAX(0, h - _limitH);
+ int maxScroll = MAX(0, h - _limitH);
_verticalScroll->_numEntries = h;
- _verticalScroll->_currentPos = _scrolledY;
+ _verticalScroll->_currentPos = CLIP((int)_scrolledY, 0, (int)maxScroll);
_verticalScroll->_entriesPerPage = _limitH;
_verticalScroll->_singleStep = _h / 4;
_verticalScroll->setPos(_w - _scrollbarWidth, 0);
_verticalScroll->setSize(_scrollbarWidth, _h - 1);
_verticalScroll->setVisible(_verticalScroll->_numEntries > _limitH); //show when there is something to scroll
_verticalScroll->recalc();
+ _fluidScroller->setBounds((float)maxScroll, (float)_limitH);
}
void RichTextWidget::reflowLayout() {
@@ -342,10 +362,12 @@ void RichTextWidget::drawWidget() {
if (_cachedTextSurface) {
int cachedHeight = _cachedTextSurface->h;
- int maxY = MAX(0, cachedHeight - _textHeight);
- int srcY = CLIP((int)_scrolledY, 0, maxY);
+ int srcY = _scrolledY < 0 ? 0 : (int)_scrolledY;
+ int destY = _scrolledY < 0 ? -(int)_scrolledY : 0;
- _surface->simpleBlitFrom(*_cachedTextSurface, Common::Rect(0, srcY, _textWidth, MIN(srcY + _textHeight, cachedHeight)), Common::Point(0, 0));
+ if (srcY < cachedHeight)
+ _surface->simpleBlitFrom(*_cachedTextSurface, Common::Rect(0, srcY, _textWidth,
+ MIN(srcY + _textHeight - destY, cachedHeight)), Common::Point(0, destY));
} else
_txtWnd->draw(_surface, 0, _scrolledY, _textWidth, _textHeight, 0, 0);
diff --git a/gui/widgets/richtext.h b/gui/widgets/richtext.h
index 6b80fba7ad3..6e4adc7487f 100644
--- a/gui/widgets/richtext.h
+++ b/gui/widgets/richtext.h
@@ -33,6 +33,7 @@ class ManagedSurface;
namespace GUI {
class ScrollBarWidget;
+class FluidScroller;
/* RichTextWidget */
class RichTextWidget : public Widget, public CommandSender {
@@ -52,6 +53,10 @@ protected:
int _textWidth;
int _textHeight;
+ float _scrollPos;
+ FluidScroller *_fluidScroller;
+ bool _isDragging;
+
Common::Path _imageArchive;
public:
@@ -69,17 +74,20 @@ public:
void handleMouseDown(int x, int y, int button, int clickCount) override;
void handleMouseUp(int x, int y, int button, int clickCount) override;
void handleMouseMoved(int x, int y, int button) override;
+ void handleTickle() override;
void handleTooltipUpdate(int x, int y) override;
void markAsDirty() override;
bool containsWidget(Widget *) const override;
+ bool wantsFocus() override { return true; }
void setImageArchive(const Common::Path &fname) { _imageArchive = fname; }
protected:
void init();
void recalc();
+ void applyScrollPos();
void drawWidget() override;
void createWidget();
void ensureWidget();
diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp
index 83354982ff0..a36fd3deff3 100644
--- a/gui/widgets/tab.cpp
+++ b/gui/widgets/tab.cpp
@@ -62,7 +62,7 @@ TabWidget::TabWidget(GuiObject *boss, const Common::String &name, ThemeEngine::T
}
void TabWidget::init() {
- setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE);
+ setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_WANT_TICKLE);
_type = kTabWidget;
_activeTab = -1;
_firstVisibleTab = 0;
@@ -300,6 +300,15 @@ void TabWidget::handleMouseWheel(int x, int y, int direction) {
}
}
+void TabWidget::handleTickle() {
+ Widget *w = _firstWidget;
+ while (w) {
+ if (w->getFlags() & WIDGET_WANT_TICKLE)
+ w->handleTickle();
+ w = w->next();
+ }
+}
+
void TabWidget::adjustTabs(int value) {
// Determine which tab is next
int tabID = _activeTab + value;
diff --git a/gui/widgets/tab.h b/gui/widgets/tab.h
index 26f531531a4..2026d71ff18 100644
--- a/gui/widgets/tab.h
+++ b/gui/widgets/tab.h
@@ -113,6 +113,7 @@ public:
void handleMouseLeft(int button) override { _lastRead = -1; };
bool handleKeyDown(Common::KeyState state) override;
void handleMouseWheel(int x, int y, int direction) override;
+ void handleTickle() override;
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
virtual int getFirstVisible() const;
virtual void setFirstVisible(int tabID, bool adjustIfRoom = false);
Commit: 441f97f4e4e8fd4e5b3207bbca0f30319eae1624
https://github.com/scummvm/scummvm/commit/441f97f4e4e8fd4e5b3207bbca0f30319eae1624
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implement drag to scroll in ScrollContainer
Changed paths:
gui/widgets/scrollcontainer.cpp
gui/widgets/scrollcontainer.h
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 0bc8ba2c21c..24c6c281d49 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -38,7 +38,7 @@ ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::Stri
}
void ScrollContainerWidget::init() {
- setFlags(WIDGET_ENABLED);
+ setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE);
_type = kScrollContainerWidget;
_backgroundType = ThemeEngine::kWidgetBackgroundPlain;
_verticalScroll = new ScrollBarWidget(this, _w, 0, 16, _h);
@@ -53,6 +53,63 @@ void ScrollContainerWidget::handleMouseWheel(int x, int y, int direction) {
_verticalScroll->handleMouseWheel(x, y, direction);
}
+void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickCount) {
+ _mouseDownY = _mouseDownStartY = y;
+ Widget *child = _childUnderMouse;
+ if (child) {
+ int childX = (x + _scrolledX) - child->getRelX();
+ int childY = (y + _scrolledY) - child->getRelY();
+ child->handleMouseDown(childX, childY, button, clickCount);
+ }
+}
+
+void ScrollContainerWidget::handleMouseMoved(int x, int y, int button) {
+ if (_mouseDownY == y)
+ return;
+
+ if (!_isDragging && ABS(y - _mouseDownStartY) > 5)
+ _isDragging = true;
+
+ if (_isDragging) {
+ int deltaY = _mouseDownY - y;
+ _mouseDownY = y;
+ _childUnderMouse = nullptr;
+
+ if (deltaY != 0) {
+ int oldPos = _scrolledY;
+ _scrolledY += deltaY;
+
+ int h = _verticalScroll->_numEntries;
+ if (_scrolledY < 0)
+ _scrolledY = 0;
+ else if (_scrolledY > h - _limitH)
+ _scrolledY = MAX(0, h - _limitH);
+
+ if (_scrolledY != oldPos) {
+ _verticalScroll->_currentPos = _scrolledY;
+ recalc();
+ markAsDirty();
+ g_gui.scheduleTopDialogRedraw();
+ }
+ }
+ }
+}
+
+void ScrollContainerWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ Widget *child = _childUnderMouse;
+ bool isDragging = _isDragging;
+
+ _mouseDownY = _mouseDownStartY = 0;
+ _isDragging = false;
+ _childUnderMouse = nullptr;
+
+ if (!isDragging && child) {
+ int childX = (x + _scrolledX) - child->getRelX();
+ int childY = (y + _scrolledY) - child->getRelY();
+ child->handleMouseUp(childX, childY, button, clickCount);
+ }
+}
+
void ScrollContainerWidget::recalc() {
_scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
_limitH = _h;
@@ -80,6 +137,7 @@ void ScrollContainerWidget::recalc() {
_verticalScroll->_singleStep = kLineHeight;
_verticalScroll->setPos(_w, _scrolledY);
_verticalScroll->setSize(_scrollbarWidth, _limitH-1);
+ _verticalScroll->recalc();
}
@@ -119,6 +177,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
}
void ScrollContainerWidget::reflowLayout() {
+ _childUnderMouse = nullptr;
Widget::reflowLayout();
if (!_dialogName.empty()) {
@@ -169,11 +228,13 @@ bool ScrollContainerWidget::containsWidget(Widget *w) const {
}
Widget *ScrollContainerWidget::findWidget(int x, int y) {
- if (_verticalScroll->isVisible() && x >= _w)
+ if (_verticalScroll->isVisible() && x >= _w) {
+ _childUnderMouse = nullptr;
return _verticalScroll;
- Widget *w = Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
- if (w)
- return w;
+ }
+ _childUnderMouse = Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
+ if (_childUnderMouse == _verticalScroll)
+ _childUnderMouse = nullptr;
return this;
}
diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h
index ea8587ec5f1..bff30dfb5cd 100644
--- a/gui/widgets/scrollcontainer.h
+++ b/gui/widgets/scrollcontainer.h
@@ -36,6 +36,10 @@ class ScrollContainerWidget: public Widget, public CommandSender {
uint32 _reflowCmd;
ThemeEngine::WidgetBackground _backgroundType;
Common::String _dialogName;
+ int _mouseDownY = 0;
+ int _mouseDownStartY = 0;
+ bool _isDragging = false;
+ Widget *_childUnderMouse = nullptr;
void recalc();
@@ -53,6 +57,9 @@ public:
void setBackgroundType(ThemeEngine::WidgetBackground backgroundType);
void handleMouseWheel(int x, int y, int direction) override;
+ void handleMouseDown(int x, int y, int button, int clickCount) override;
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
+ void handleMouseMoved(int x, int y, int button) override;
// We overload getChildY to make sure child widgets are positioned correctly.
// Essentially this compensates for the space taken up by the tab title header.
@@ -60,6 +67,7 @@ public:
int16 getChildY() const override;
uint16 getWidth() const override;
uint16 getHeight() const override;
+ bool wantsFocus() override { return true; }
void draw() override;
void markAsDirty() override;
Commit: 84dab33d07052c74417878e233bcf8eab0668a4d
https://github.com/scummvm/scummvm/commit/84dab33d07052c74417878e233bcf8eab0668a4d
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Implenet Fluid Scroll in ScrollContainer
Changed paths:
gui/widgets/scrollcontainer.cpp
gui/widgets/scrollcontainer.h
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 24c6c281d49..345de340810 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -27,6 +27,7 @@
namespace GUI {
+const int ScrollContainerWidget::kDragThreshold = 5;
ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, int x, int y, int w, int h, uint32 reflowCmd)
: Widget(boss, x, y, w, h), CommandSender(nullptr), _reflowCmd(reflowCmd) {
init();
@@ -38,23 +39,30 @@ ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::Stri
}
void ScrollContainerWidget::init() {
- setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE);
+ setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_WANT_TICKLE | WIDGET_RETAIN_FOCUS);
_type = kScrollContainerWidget;
_backgroundType = ThemeEngine::kWidgetBackgroundPlain;
_verticalScroll = new ScrollBarWidget(this, _w, 0, 16, _h);
_verticalScroll->setTarget(this);
_scrolledX = 0;
_scrolledY = 0;
+ _scrollPos = 0.0f;
_limitH = 140;
+ _fluidScroller = new FluidScroller();
recalc();
}
void ScrollContainerWidget::handleMouseWheel(int x, int y, int direction) {
- _verticalScroll->handleMouseWheel(x, y, direction);
+ if (!isEnabled())
+ return;
+
+ _fluidScroller->handleMouseWheel(direction, (float)_verticalScroll->_singleStep);
}
void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickCount) {
_mouseDownY = _mouseDownStartY = y;
+ _isMouseDown = true;
+ _fluidScroller->stopAnimation();
Widget *child = _childUnderMouse;
if (child) {
int childX = (x + _scrolledX) - child->getRelX();
@@ -64,10 +72,10 @@ void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickC
}
void ScrollContainerWidget::handleMouseMoved(int x, int y, int button) {
- if (_mouseDownY == y)
+ if (!_isMouseDown || _mouseDownY == y)
return;
- if (!_isDragging && ABS(y - _mouseDownStartY) > 5)
+ if (!_isDragging && ABS(y - _mouseDownStartY) > kDragThreshold)
_isDragging = true;
if (_isDragging) {
@@ -76,30 +84,38 @@ void ScrollContainerWidget::handleMouseMoved(int x, int y, int button) {
_childUnderMouse = nullptr;
if (deltaY != 0) {
- int oldPos = _scrolledY;
- _scrolledY += deltaY;
-
- int h = _verticalScroll->_numEntries;
- if (_scrolledY < 0)
- _scrolledY = 0;
- else if (_scrolledY > h - _limitH)
- _scrolledY = MAX(0, h - _limitH);
-
- if (_scrolledY != oldPos) {
- _verticalScroll->_currentPos = _scrolledY;
- recalc();
- markAsDirty();
- g_gui.scheduleTopDialogRedraw();
- }
+ _fluidScroller->feedDrag(g_system->getMillis(), deltaY);
+ _scrollPos = _fluidScroller->getVisualPosition();
+ applyScrollPos();
}
}
}
+void ScrollContainerWidget::handleTickle() {
+ if (_fluidScroller->update(g_system->getMillis(), _scrollPos))
+ applyScrollPos();
+}
+
+void ScrollContainerWidget::applyScrollPos() {
+ _scrolledY = (int16)_scrollPos;
+ int h = _verticalScroll->_numEntries;
+ int maxScroll = MAX(0, h - _limitH);
+ _verticalScroll->_currentPos = CLIP<int16>(_scrolledY, 0, maxScroll);
+ _verticalScroll->setPos(_w, _scrolledY);
+ _verticalScroll->recalc();
+ markAsDirty();
+ g_gui.scheduleTopDialogRedraw();
+}
+
void ScrollContainerWidget::handleMouseUp(int x, int y, int button, int clickCount) {
Widget *child = _childUnderMouse;
bool isDragging = _isDragging;
+ if (_isMouseDown && _isDragging)
+ _fluidScroller->startFling();
+
_mouseDownY = _mouseDownStartY = 0;
+ _isMouseDown = false;
_isDragging = false;
_childUnderMouse = nullptr;
@@ -129,19 +145,24 @@ void ScrollContainerWidget::recalc() {
int h = max - min;
if (h <= _limitH) _scrolledY = 0;
- if (_scrolledY > h - _limitH) _scrolledY = 0;
+ else if (!_fluidScroller->isAnimating() && !_isMouseDown)
+ _scrolledY = CLIP<int16>(_scrolledY, 0, h - _limitH);
_verticalScroll->_numEntries = h;
- _verticalScroll->_currentPos = _scrolledY;
+ int maxScroll = MAX(0, h - _limitH);
+ _verticalScroll->_currentPos = CLIP<int16>(_scrolledY, 0, maxScroll);
_verticalScroll->_entriesPerPage = _limitH;
_verticalScroll->_singleStep = kLineHeight;
_verticalScroll->setPos(_w, _scrolledY);
_verticalScroll->setSize(_scrollbarWidth, _limitH-1);
_verticalScroll->recalc();
+ _fluidScroller->setBounds((float)maxScroll, _limitH);
}
-ScrollContainerWidget::~ScrollContainerWidget() {}
+ScrollContainerWidget::~ScrollContainerWidget() {
+ delete _fluidScroller;
+}
int16 ScrollContainerWidget::getChildX() const {
return getAbsX() - _scrolledX;
@@ -168,6 +189,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
switch (cmd) {
case kSetPositionCmd:
_scrolledY = _verticalScroll->_currentPos;
+ _scrollPos = _fluidScroller->setPosition((float)_scrolledY, false);
reflowLayout();
g_gui.scheduleTopDialogRedraw();
break;
diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h
index bff30dfb5cd..37c4582e805 100644
--- a/gui/widgets/scrollcontainer.h
+++ b/gui/widgets/scrollcontainer.h
@@ -25,6 +25,7 @@
#include "gui/widget.h"
#include "common/str.h"
#include "gui/widgets/scrollbar.h"
+#include "gui/animation/FluidScroll.h"
namespace GUI {
@@ -37,11 +38,16 @@ class ScrollContainerWidget: public Widget, public CommandSender {
ThemeEngine::WidgetBackground _backgroundType;
Common::String _dialogName;
int _mouseDownY = 0;
+ static const int kDragThreshold;
int _mouseDownStartY = 0;
+ bool _isMouseDown = false;
bool _isDragging = false;
+ float _scrollPos = 0.0f;
+ FluidScroller *_fluidScroller = nullptr;
Widget *_childUnderMouse = nullptr;
void recalc();
+ void applyScrollPos();
public:
ScrollContainerWidget(GuiObject *boss, int x, int y, int w, int h, uint32 reflowCmd = 0);
@@ -60,6 +66,7 @@ public:
void handleMouseDown(int x, int y, int button, int clickCount) override;
void handleMouseUp(int x, int y, int button, int clickCount) override;
void handleMouseMoved(int x, int y, int button) override;
+ void handleTickle() override;
// We overload getChildY to make sure child widgets are positioned correctly.
// Essentially this compensates for the space taken up by the tab title header.
Commit: c041092694285068d2a83f53fc7f6e460d4d1d8e
https://github.com/scummvm/scummvm/commit/c041092694285068d2a83f53fc7f6e460d4d1d8e
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-04-20T23:33:23+02:00
Commit Message:
GUI: Centralize scroll step size logic in FluidScroller
Changed paths:
gui/about.cpp
gui/animation/FluidScroll.cpp
gui/animation/FluidScroll.h
gui/widgets/grid.cpp
gui/widgets/groupedlist.cpp
gui/widgets/list.cpp
gui/widgets/richtext.cpp
gui/widgets/scrollcontainer.cpp
diff --git a/gui/about.cpp b/gui/about.cpp
index c7659ec9122..ac719ba54d0 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -437,7 +437,7 @@ void AboutDialog::handleMouseMoved(int x, int y, int button) {
void AboutDialog::handleMouseWheel(int x, int y, int direction) {
_autoScroll = false;
- _fluidScroller->handleMouseWheel(direction, (float)_lineHeight);
+ _fluidScroller->handleMouseWheel(direction);
}
void AboutDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
@@ -529,7 +529,7 @@ void AboutDialog::reflowLayout() {
buildLines();
int maxScroll = MAX(0, (int)(_lines.size() * _lineHeight) - _textRect.height());
- _fluidScroller->setBounds((float)maxScroll, _textRect.height());
+ _fluidScroller->setBounds((float)maxScroll, _textRect.height(), (float)_scrollbar->_singleStep);
}
diff --git a/gui/animation/FluidScroll.cpp b/gui/animation/FluidScroll.cpp
index 830f31bd269..e8a1051ca9e 100644
--- a/gui/animation/FluidScroll.cpp
+++ b/gui/animation/FluidScroll.cpp
@@ -96,6 +96,7 @@ FluidScroller::FluidScroller() :
_scrollPosRaw(0.0f),
_animationOffset(0.0f),
_maxScroll(0.0f),
+ _stepSize(1.0f),
_viewportHeight(0),
_lastWheelTime(0),
_initialVelocity(0.0f),
@@ -104,9 +105,10 @@ FluidScroller::FluidScroller() :
_impactVelocity(0.0f) {
}
-void FluidScroller::setBounds(float maxScroll, int viewportHeight) {
+void FluidScroller::setBounds(float maxScroll, int viewportHeight, float stepSize) {
_maxScroll = maxScroll;
_viewportHeight = viewportHeight;
+ _stepSize = stepSize;
}
void FluidScroller::reset() {
@@ -169,8 +171,8 @@ void FluidScroller::feedWheel(uint32 time, float deltaY) {
startFling(velocity);
}
-void FluidScroller::handleMouseWheel(int direction, float stepSize, float multiplier) {
- float stepping = stepSize * (float)direction * multiplier;
+void FluidScroller::handleMouseWheel(int direction, float multiplier) {
+ float stepping = _stepSize * (float)direction * multiplier;
if (stepping == 0.0f)
return;
diff --git a/gui/animation/FluidScroll.h b/gui/animation/FluidScroll.h
index 4c2114a6b21..8ec0ff07244 100644
--- a/gui/animation/FluidScroll.h
+++ b/gui/animation/FluidScroll.h
@@ -40,8 +40,9 @@ public:
* Configure the constraints for the content
* @param maxScroll The maximum scrollable distance (total height - viewport height)
* @param viewportHeight The height of the scrolling area, used for rubber-band range
+ * @param stepSize Default scroll step (usually _singleStep)
*/
- void setBounds(float maxScroll, int viewportHeight);
+ void setBounds(float maxScroll, int viewportHeight, float stepSize);
void reset();
@@ -67,10 +68,9 @@ public:
/**
* Handle mouse wheel input
* @param direction Scroll direction
- * @param stepSize usually _scrollBar->_singleStep
* @param multiplier Speed multiplier for the scroll
*/
- void handleMouseWheel(int direction, float stepSize, float multiplier = 1.0f);
+ void handleMouseWheel(int direction, float multiplier = 1.0f);
// Check if there is an active animation (fling or spring-back)
bool isAnimating() const { return _mode != kModeNone; }
@@ -125,6 +125,7 @@ private:
float _scrollPosRaw; // Physical position (can go out of bounds)
float _animationOffset; // Anchor position used as the starting point for animation offsets
float _maxScroll;
+ float _stepSize;
int _viewportHeight;
// Fling parameter
diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index 0132e4060be..d80081287b9 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -1012,7 +1012,7 @@ void GridWidget::selectVisualRange(int startPos, int endPos) {
}
void GridWidget::handleMouseWheel(int x, int y, int direction) {
- _fluidScroller->handleMouseWheel(direction, (float)_scrollBar->_singleStep);
+ _fluidScroller->handleMouseWheel(direction);
}
void GridWidget::handleMouseDown(int x, int y, int button, int clickCount) {
@@ -1266,7 +1266,7 @@ void GridWidget::reflowLayout() {
}
scrollBarRecalc();
int maxScroll = MAX(0, _scrollBar->_numEntries - _scrollBar->_entriesPerPage);
- _fluidScroller->setBounds((float)maxScroll, _scrollBar->_entriesPerPage);
+ _fluidScroller->setBounds((float)maxScroll, _scrollBar->_entriesPerPage, (float)_scrollBar->_singleStep);
markAsDirty();
}
@@ -1291,7 +1291,7 @@ void GridWidget::scrollBarRecalc() {
_scrollBar->recalc();
maxScroll = MAX(0, _scrollBar->_numEntries - _scrollBar->_entriesPerPage);
- _fluidScroller->setBounds((float)maxScroll, _scrollBar->_entriesPerPage);
+ _fluidScroller->setBounds((float)maxScroll, _scrollBar->_entriesPerPage, (float)_scrollBar->_singleStep);
}
void GridWidget::setFilter(const Common::U32String &filter) {
diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index cd5cf359aad..28147a65546 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -356,7 +356,7 @@ void GroupedListWidget::handleMouseUp(int x, int y, int button, int clickCount)
}
void GroupedListWidget::handleMouseWheel(int x, int y, int direction) {
- _fluidScroller->handleMouseWheel(direction, (float)_scrollBar->_singleStep);
+ _fluidScroller->handleMouseWheel(direction);
}
void GroupedListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index 5f75f3a5cbd..7a3559c4498 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -355,7 +355,7 @@ void ListWidget::scrollBarRecalc() {
_scrollBar->recalc();
int maxScroll = MAX(0, (int)(_scrollBar->_numEntries - _scrollBar->_entriesPerPage) * lineHeight);
- _fluidScroller->setBounds((float)maxScroll, _h - _topPadding - _bottomPadding);
+ _fluidScroller->setBounds((float)maxScroll, _h - _topPadding - _bottomPadding, (float)_scrollBar->_singleStep);
}
void ListWidget::handleTickle() {
@@ -459,7 +459,7 @@ void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
}
void ListWidget::handleMouseWheel(int x, int y, int direction) {
- _fluidScroller->handleMouseWheel(direction, (float)_scrollBar->_singleStep);
+ _fluidScroller->handleMouseWheel(direction);
}
void ListWidget::handleMouseMoved(int x, int y, int button) {
diff --git a/gui/widgets/richtext.cpp b/gui/widgets/richtext.cpp
index a63a254bbb9..03a15076e41 100644
--- a/gui/widgets/richtext.cpp
+++ b/gui/widgets/richtext.cpp
@@ -103,7 +103,7 @@ RichTextWidget::~RichTextWidget() {
}
void RichTextWidget::handleMouseWheel(int x, int y, int direction) {
- _fluidScroller->handleMouseWheel(direction, (float)_verticalScroll->_singleStep);
+ _fluidScroller->handleMouseWheel(direction);
applyScrollPos();
}
@@ -245,7 +245,7 @@ void RichTextWidget::recalc() {
_verticalScroll->setSize(_scrollbarWidth, _h - 1);
_verticalScroll->setVisible(_verticalScroll->_numEntries > _limitH); //show when there is something to scroll
_verticalScroll->recalc();
- _fluidScroller->setBounds((float)maxScroll, (float)_limitH);
+ _fluidScroller->setBounds((float)maxScroll, (float)_limitH, (float)_verticalScroll->_singleStep);
}
}
@@ -328,7 +328,7 @@ void RichTextWidget::createWidget() {
_verticalScroll->setSize(_scrollbarWidth, _h - 1);
_verticalScroll->setVisible(_verticalScroll->_numEntries > _limitH); //show when there is something to scroll
_verticalScroll->recalc();
- _fluidScroller->setBounds((float)maxScroll, (float)_limitH);
+ _fluidScroller->setBounds((float)maxScroll, (float)_limitH, (float)_verticalScroll->_singleStep);
}
void RichTextWidget::reflowLayout() {
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 345de340810..0ac21c93241 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -56,7 +56,7 @@ void ScrollContainerWidget::handleMouseWheel(int x, int y, int direction) {
if (!isEnabled())
return;
- _fluidScroller->handleMouseWheel(direction, (float)_verticalScroll->_singleStep);
+ _fluidScroller->handleMouseWheel(direction);
}
void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickCount) {
@@ -156,7 +156,7 @@ void ScrollContainerWidget::recalc() {
_verticalScroll->setPos(_w, _scrolledY);
_verticalScroll->setSize(_scrollbarWidth, _limitH-1);
_verticalScroll->recalc();
- _fluidScroller->setBounds((float)maxScroll, _limitH);
+ _fluidScroller->setBounds((float)maxScroll, _limitH, (float)_verticalScroll->_singleStep);
}
More information about the Scummvm-git-logs
mailing list