[Scummvm-git-logs] scummvm master -> fba6cfd6e5cbab2e8cfc6f9b4b42d65f880cdb99

sev- noreply at scummvm.org
Sat Jun 13 13:52:56 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:
6c3c158ae3 GUI: Fix collapsed group state lost when switching launcher views
1a83c9a0cf GUI: Fix wrong group collapsed after Launcher view change
59a71948da GUI: Sort groups with no attribute value last in GridWidget
25930ec055 GUI: Add configuration option to toggle kinetic scrolling support
387085c700 GUI: Stop fluid animation on click
3f1e93fb37 GUI: Preserve selection states in list widgets when applying search filters
e6c2e82c19 GUI: Preserve launcher multi-selections when switching views
02e4a55c52 GUI: Preserve launcher grid selections when changing grouping
09c15f3672 JANITORIAL: Remove trailing spaces
a9e0481ffa BASE: Enable kinetic scrolling by default
fba6cfd6e5 GUI: Added kinetic scrolling checkbox to GUI Options. Bump theme version


Commit: 6c3c158ae30e7dd815fa69685b889c1437e8542b
    https://github.com/scummvm/scummvm/commit/6c3c158ae30e7dd815fa69685b889c1437e8542b
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:00+02:00

Commit Message:
GUI: Fix collapsed group state lost when switching launcher views

Fixes #16772
Prevent saving closed groups in LauncherSimple::updateListing() on the initial build to avoid overwriting the config saved by the previous view's destructor.

Changed paths:
    gui/launcher.cpp
    gui/launcher.h


diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index e0b5157e3b0..6351969fea0 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -1111,7 +1111,7 @@ static const int kSelPosGroupingChange = -2;
 
 LauncherSimple::LauncherSimple(const Common::String &title)
 	: LauncherDialog(title),
-	_list(nullptr) {
+	_list(nullptr), _listInitialized(false) {
 	build();
 }
 
@@ -1255,10 +1255,13 @@ void LauncherSimple::updateListing(int selPos) {
 		savedSelection = _list->saveSelection();
 	}
 
-	// Preserve the current collapsed groups before rebuilding the grouped list
-	if (_groupBy != kGroupByNone) {
+	/* Preserve the current collapsed groups before rebuilding the grouped list
+	 * Skip this on the very first call as it would overwrite the config state
+	 * saved by the previous view's destructor */
+	if (_groupBy != kGroupByNone && _listInitialized) {
 		_list->saveClosedGroups(Common::U32String(groupingModes[_groupBy].name));
 	}
+	_listInitialized = true;
 
 	_list->setList(l);
 
diff --git a/gui/launcher.h b/gui/launcher.h
index 0c3b6295e2e..427b6a8daf6 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -323,6 +323,7 @@ protected:
 
 private:
 	GroupedListWidget *_list;
+	bool _listInitialized; // Whether the list has already been initialized
 };
 
 } // End of namespace GUI


Commit: 1a83c9a0cf8b132874899ac3bb0494eccf6eb616
    https://github.com/scummvm/scummvm/commit/1a83c9a0cf8b132874899ac3bb0494eccf6eb616
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:01+02:00

Commit Message:
GUI: Fix wrong group collapsed after Launcher view change

_groupHeaders is sorted alphabetically, but _groupExpanded is indexed by groupID. Use _groupValueIndex to get the right index.

Changed paths:
    gui/widgets/grid.cpp
    gui/widgets/groupedlist.cpp


diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index a7aa469a2be..94d2d9604f6 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -276,7 +276,8 @@ void GridWidget::loadClosedGroups(const Common::U32String &groupName) {
 			// See if the hidden group is in our group headers still, if so, hide it
 			for (Common::U32StringArray::size_type i = 0; i < _groupHeaders.size(); ++i) {
 				if (_groupHeaders[i] == tok || (tok == "unnamed" && _groupHeaders[i].size() == 0)) {
-					_groupExpanded[i] = false;
+					uint groupID = _groupValueIndex[_groupHeaders[i]];
+					_groupExpanded[groupID] = false;
 					break;
 				}
 			}
@@ -291,7 +292,8 @@ void GridWidget::saveClosedGroups(const Common::U32String &groupName) {
 	// Save the hidden groups to the config
 	Common::String hiddenGroups;
 	for (Common::U32StringArray::size_type i = 0; i < _groupHeaders.size(); ++i) {
-		if (!_groupExpanded[i]) {
+		uint groupID = _groupValueIndex[_groupHeaders[i]];
+		if (!_groupExpanded[groupID]) {
 			if (_groupHeaders[i].size()) {
 				hiddenGroups += _groupHeaders[i];
 			} else {
diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index e2a89be7ca3..988bbc3ff1a 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -171,7 +171,8 @@ void GroupedListWidget::loadClosedGroups(const Common::U32String &groupName) {
 			// See if the hidden group is in our group headers still, if so, hide it
 			for (Common::U32StringArray::size_type i = 0; i < _groupHeaders.size(); ++i) {
 				if (_groupHeaders[i] == tok || (tok == "unnamed" && _groupHeaders[i].size() == 0)) {
-					_groupExpanded[i] = false;
+					uint groupID = _groupValueIndex[_groupHeaders[i]];
+					_groupExpanded[groupID] = false;
 					break;
 				}
 			}
@@ -184,7 +185,8 @@ void GroupedListWidget::saveClosedGroups(const Common::U32String &groupName) {
 	// Save the hidden groups to the config
 	Common::String hiddenGroups;
 	for (Common::U32StringArray::size_type i = 0; i < _groupHeaders.size(); ++i) {
-		if (!_groupExpanded[i]) {
+		uint groupID = _groupValueIndex[_groupHeaders[i]];
+		if (!_groupExpanded[groupID]) {
 			if (_groupHeaders[i].size()) {
 				hiddenGroups += _groupHeaders[i];
 			} else {


Commit: 59a71948da54e6467620defeaeb38851296641ea
    https://github.com/scummvm/scummvm/commit/59a71948da54e6467620defeaeb38851296641ea
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:01+02:00

Commit Message:
GUI: Sort groups with no attribute value last in GridWidget

Matches with ListWidget sorting

Changed paths:
    gui/widgets/grid.cpp


diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index 94d2d9604f6..f27acdec152 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -653,7 +653,10 @@ void GridWidget::sortGroups() {
 
 	if (_filter.empty()) {
 		// No filter -> display everything with group headers
-		Common::sort(_groupHeaders.begin(), _groupHeaders.end());
+		Common::sort(_groupHeaders.begin(), _groupHeaders.end(),
+			[](const Common::U32String &first, const Common::U32String &second) {
+				return first.empty() ? 0 : second.empty() ? 1 : first < second;
+			});
 
 		// Avoid reallocation during iteration: that would invalidate our _sortedEntryList items
 		_headerEntryList.reserve(_groupHeaders.size());


Commit: 25930ec055b3e258689f5a9a799e05345e0bc14c
    https://github.com/scummvm/scummvm/commit/25930ec055b3e258689f5a9a799e05345e0bc14c
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:01+02:00

Commit Message:
GUI: Add configuration option to toggle kinetic scrolling support

Changed paths:
    base/commandLine.cpp
    gui/animation/FluidScroll.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 1f5ae0583c6..04e8182e085 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -402,6 +402,7 @@ void registerDefaults() {
 	ConfMan.registerDefault("gui_return_to_launcher_at_exit", false);
 	ConfMan.registerDefault("gui_launcher_chooser", "list");
 	ConfMan.registerDefault("grid_items_per_row", 4);
+	ConfMan.registerDefault("gui_kinetic_scrolling", false);
 	// Specify threshold for scanning directories in the launcher
 	// If number of game entries in scummvm.ini exceeds the specified
 	// number, then skip scanning. -1 = scan always
diff --git a/gui/animation/FluidScroll.cpp b/gui/animation/FluidScroll.cpp
index 060a1603360..3605f0d3386 100644
--- a/gui/animation/FluidScroll.cpp
+++ b/gui/animation/FluidScroll.cpp
@@ -26,6 +26,7 @@
 
 #include "common/system.h"
 #include "common/util.h"
+#include "common/config-manager.h"
 #include "gui/animation/FluidScroll.h"
 
 namespace GUI {
@@ -127,6 +128,10 @@ void FluidScroller::stopAnimation() {
 
 void FluidScroller::feedDrag(uint32 time, int deltaY) {
 	_scrollPosRaw += (float)deltaY;
+	if (!ConfMan.getBool("gui_kinetic_scrolling")) {
+		_scrollPosRaw = CLIP(_scrollPosRaw, 0.0f, _maxScroll);
+		return;
+	}
 	_velocityTracker.addPoint(time, _scrollPosRaw);
 }
 
@@ -142,7 +147,7 @@ void FluidScroller::startFling() {
 }
 
 void FluidScroller::startFling(float velocity) {
-	if (fabsf(velocity) < 0.1f) {
+	if (!ConfMan.getBool("gui_kinetic_scrolling") || fabsf(velocity) < 0.1f) {
 		checkBoundaries();
 		return;
 	}
@@ -183,6 +188,11 @@ void FluidScroller::handleMouseWheel(int direction, float multiplier) {
 	if (stepping == 0.0f)
 		return;
 
+	if (!ConfMan.getBool("gui_kinetic_scrolling")) {
+		_scrollPosRaw = CLIP(_scrollPosRaw + stepping, 0.0f, _maxScroll);
+		_mode = kModeNone;
+		return;
+	}
 	feedWheel(g_system->getMillis(), stepping);
 }
 
@@ -198,8 +208,15 @@ void FluidScroller::absorb(float velocity, float distance) {
 }
 
 bool FluidScroller::update(uint32 time, float &outVisualPos) {
+	if (!ConfMan.getBool("gui_kinetic_scrolling")) {
+		_mode = kModeNone;
+	}
 	if (_mode == kModeNone) {
-		outVisualPos = getVisualPosition();
+		float visualPos = getVisualPosition();
+		if (outVisualPos != visualPos) {
+			outVisualPos = visualPos;
+			return true;
+		}
 		return false;
 	}
 
@@ -248,6 +265,8 @@ bool FluidScroller::update(uint32 time, float &outVisualPos) {
 }
 
 float FluidScroller::getVisualPosition() const {
+	if (!ConfMan.getBool("gui_kinetic_scrolling"))
+		return CLIP(_scrollPosRaw, 0.0f, _maxScroll);
 	float rubberBandRange = (float)_viewportHeight * kRubberBandStretchFraction;
 
 	if (_scrollPosRaw < 0)
@@ -259,6 +278,11 @@ float FluidScroller::getVisualPosition() const {
 }
 
 void FluidScroller::checkBoundaries() {
+	if (!ConfMan.getBool("gui_kinetic_scrolling")) {
+		_scrollPosRaw = CLIP(_scrollPosRaw, 0.0f, _maxScroll);
+		_mode = kModeNone;
+		return;
+	}
 	if (_scrollPosRaw < 0) {
 		absorb(0, _scrollPosRaw);
 		_animationOffset = 0;


Commit: 387085c700964ed3ea35ff5c60df70ee3a7777c8
    https://github.com/scummvm/scummvm/commit/387085c700964ed3ea35ff5c60df70ee3a7777c8
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:01+02:00

Commit Message:
GUI: Stop fluid animation on click

Stop fluid animation on a mouse left button click in List, Grid and ScrollContainer widgets

Changed paths:
    gui/widgets/grid.cpp
    gui/widgets/grid.h
    gui/widgets/groupedlist.cpp
    gui/widgets/list.cpp
    gui/widgets/list.h
    gui/widgets/scrollcontainer.cpp
    gui/widgets/scrollcontainer.h


diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index f27acdec152..41d1ef4b1f6 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -539,6 +539,7 @@ GridWidget::GridWidget(GuiObject *boss, const Common::String &name)
 	_dragLastY = 0;
 
 	_fluidScroller = new FluidScroller();
+	_wasAnimating = false;
 
 	_filterMatcher = GridWidgetDefaultMatcher;
 	_filterMatcherArg = nullptr;
@@ -1046,6 +1047,7 @@ void GridWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 		_dragLastY = y;
 	}
 	_selectionPending = true;
+	_wasAnimating = _fluidScroller->isAnimating();
 	_fluidScroller->stopAnimation();
 }
 
@@ -1057,7 +1059,7 @@ void GridWidget::handleMouseUp(int x, int y, int button, int clickCount) {
 	_isDragging = false;
 	_selectionPending = false;
 
-	if (wasPending && !wasDragging) {
+	if (wasPending && !wasDragging && !_wasAnimating) {
 		// Find which item was clicked and select it
 		Widget *w = findWidget(x, y);
 		if (w && w != this && w->getType() == kContainerWidget)
@@ -1066,6 +1068,7 @@ void GridWidget::handleMouseUp(int x, int y, int button, int clickCount) {
 
 	if (wasDragging)
 		_fluidScroller->startFling();
+	_wasAnimating = false;
 }
 
 void GridWidget::handleMouseMoved(int x, int y, int button) {
@@ -1117,6 +1120,7 @@ bool GridWidget::handleKeyUp(Common::KeyState state) {
 void GridWidget::lostFocusWidget() {
 	_isMouseDown = _isDragging = false;
 	_dragStartY = _dragLastY = 0;
+	_wasAnimating = false;
 }
 
 void GridWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
diff --git a/gui/widgets/grid.h b/gui/widgets/grid.h
index 920550f4764..e2187eb294b 100644
--- a/gui/widgets/grid.h
+++ b/gui/widgets/grid.h
@@ -180,6 +180,7 @@ protected:
 	static const int kDragThreshold = 5;
 
 	FluidScroller *_fluidScroller;
+	bool _wasAnimating;
 	GridItemWidget *_highlightedItem = nullptr;
 
 public:
diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index 988bbc3ff1a..c827b37cea5 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -268,6 +268,7 @@ void GroupedListWidget::handleMouseDown(int x, int y, int button, int clickCount
 	if (button == 1) {
 		_dragStartY = y;
 		_dragLastY = y;
+		_wasAnimating = _fluidScroller->isAnimating();
 		_fluidScroller->stopAnimation();
 	}
 
@@ -283,7 +284,7 @@ void GroupedListWidget::handleMouseUp(int x, int y, int button, int clickCount)
 		if (_isMouseDown && button == 1 && _isDragging)
 			_fluidScroller->startFling();
 
-		if (_isMouseDown && !_isDragging) {
+		if (_isMouseDown && !_isDragging && !_wasAnimating) {
 			int newSelectedItem = findItem(x, y);
 			if (newSelectedItem != -1) {
 				if (isGroupHeader(_listIndex[newSelectedItem])) {
@@ -349,12 +350,13 @@ 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))) {
+	if (!_wasAnimating && clickCount == 2 && (_selectedItem == findItem(x, y))) {
 		int selectID = getSelected();
 		if (selectID >= 0) {
 			sendCommand(kListItemDoubleClickedCmd, _selectedItem);
 		}
 	}
+	_wasAnimating = false;
 }
 
 void GroupedListWidget::handleMouseWheel(int x, int y, int direction) {
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index c3edc794a9f..67454c0caae 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -83,6 +83,7 @@ ListWidget::ListWidget(Dialog *boss, const Common::String &name, const Common::U
 
 	_scrollPos = 0.0f;
 	_fluidScroller = new FluidScroller();
+	_wasAnimating = false;
 	_isMouseDown = false;
 	_isDragging = false;
 	_dragStartY = _dragLastY = 0;
@@ -136,6 +137,7 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, bool scale, con
 
 	_scrollPos = 0.0f;
 	_fluidScroller = new FluidScroller();
+	_wasAnimating = false;
 	_isMouseDown = false;
 	_isDragging = false;
 	_dragStartY = _dragLastY = 0;
@@ -383,6 +385,7 @@ void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 	_isMouseDown = true;
 	_isDragging = false;
 	_dragLastY = 0;
+	_wasAnimating = _fluidScroller->isAnimating();
 	_fluidScroller->stopAnimation();
 
 	if (button == 1) {
@@ -399,7 +402,7 @@ void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) {
 		if (_isMouseDown && button == 1 && _isDragging)
 			_fluidScroller->startFling();
 
-		if (_isMouseDown && !_isDragging) {
+		if (_isMouseDown && !_isDragging && !_wasAnimating) {
 			// Perform selection
 			int newSelectedItem = findItem(x, y);
 			if (newSelectedItem != -1) {
@@ -453,10 +456,11 @@ 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)) &&
+	if (!_wasAnimating && clickCount == 2 && (_selectedItem == findItem(x, y)) &&
 		_selectedItem >= 0) {
 		sendCommand(kListItemDoubleClickedCmd, _selectedItem);
 	}
+	_wasAnimating = false;
 }
 
 void ListWidget::handleMouseWheel(int x, int y, int direction) {
diff --git a/gui/widgets/list.h b/gui/widgets/list.h
index c0196d58d44..42fcbf89f69 100644
--- a/gui/widgets/list.h
+++ b/gui/widgets/list.h
@@ -81,6 +81,7 @@ protected:
 
 	float			_scrollPos;
 	FluidScroller	*_fluidScroller;
+	bool			_wasAnimating;
 	bool			_isMouseDown;
 	bool			_isDragging;
 	int				_dragStartY;
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 9fca3580f44..352e5c4690a 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -49,6 +49,7 @@ void ScrollContainerWidget::init() {
 	_scrollPos = 0.0f;
 	_limitH = 140;
 	_fluidScroller = new FluidScroller();
+	_wasAnimating = false;
 	recalc();
 }
 
@@ -62,7 +63,11 @@ void ScrollContainerWidget::handleMouseWheel(int x, int y, int direction) {
 void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 	_mouseDownY = _mouseDownStartY = y;
 	_isMouseDown = true;
+	_wasAnimating = _fluidScroller->isAnimating();
 	_fluidScroller->stopAnimation();
+	if (_wasAnimating)
+		return;
+
 	Widget *child = _childUnderMouse;
 	if (child) {
 		int childX = x - (child->getAbsX() - getAbsX());
@@ -124,11 +129,12 @@ void ScrollContainerWidget::handleMouseUp(int x, int y, int button, int clickCou
 	_isDragging = false;
 	_childUnderMouse = nullptr;
 
-	if (!isDragging && child) {
+	if (!isDragging && child && !_wasAnimating) {
 		int childX = x - (child->getAbsX() - getAbsX());
 		int childY = y - (child->getAbsY() - getAbsY());
 		child->handleMouseUp(childX, childY, button, clickCount);
 	}
+	_wasAnimating = false;
 }
 
 void ScrollContainerWidget::recalc() {
@@ -251,6 +257,7 @@ void ScrollContainerWidget::markAsDirty() {
 void ScrollContainerWidget::lostFocusWidget() {
 	_isMouseDown = _isDragging = false;
 	_mouseDownY = _mouseDownStartY = 0;
+	_wasAnimating = false;
 }
 
 bool ScrollContainerWidget::containsWidget(Widget *w) const {
diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h
index 46ac530dd17..d62f4a31beb 100644
--- a/gui/widgets/scrollcontainer.h
+++ b/gui/widgets/scrollcontainer.h
@@ -42,6 +42,7 @@ class ScrollContainerWidget: public Widget, public CommandSender {
 	int _mouseDownStartY = 0;
 	bool _isMouseDown = false;
 	bool _isDragging = false;
+	bool _wasAnimating = false;
 	float _scrollPos = 0.0f;
 	FluidScroller *_fluidScroller = nullptr;
 	Widget *_childUnderMouse = nullptr;


Commit: 3f1e93fb378f0da41421127a32b7c20e669e2003
    https://github.com/scummvm/scummvm/commit/3f1e93fb378f0da41421127a32b7c20e669e2003
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:02+02:00

Commit Message:
GUI: Preserve selection states in list widgets when applying search filters

Changed paths:
    gui/widgets/groupedlist.cpp
    gui/widgets/list.cpp


diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index c827b37cea5..ea166077f2e 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -541,8 +541,6 @@ void GroupedListWidget::setFilter(const Common::U32String &filter, bool redraw)
 	if (_filter == filt) // Filter was not changed
 		return;
 
-	int selectedItem = getSelected();
-
 	_filter = filt;
 
 	if (_filter.empty()) {
@@ -582,9 +580,7 @@ void GroupedListWidget::setFilter(const Common::U32String &filter, bool redraw)
 	_scrollPos = 0.0f;
 	_fluidScroller->setPosition(_scrollPos);
 	_selectedItem = -1;
-	// Try to preserve the previous selection
-	if (selectedItem != -1)
-		setSelected(selectedItem);
+	_lastSelectionStartItem = -1;
 
 	if (redraw) {
 		scrollBarRecalc();
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index 67454c0caae..697d0625acf 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -1136,6 +1136,7 @@ void ListWidget::setFilter(const Common::U32String &filter, bool redraw) {
 	_scrollPos = 0.0f;
 	_fluidScroller->setPosition(_scrollPos);
 	_selectedItem = -1;
+	_lastSelectionStartItem = -1;
 
 	if (redraw) {
 		scrollBarRecalc();


Commit: e6c2e82c195920c9942292be0c1a41b4cf90cf28
    https://github.com/scummvm/scummvm/commit/e6c2e82c195920c9942292be0c1a41b4cf90cf28
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:02+02:00

Commit Message:
GUI: Preserve launcher multi-selections when switching views

Changed paths:
    gui/launcher.cpp
    gui/launcher.h


diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 6351969fea0..ad1f4344124 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -1099,7 +1099,30 @@ int LauncherChooser::runModal() {
 	do {
 		ret = _impl->run();
 		if (ret == kSwitchLauncherDialog) {
+			Common::StringArray selectedDomains;
+			const Common::Array<bool> &selections = _impl->getSelectedItems();
+			const Common::StringArray &domains = _impl->getDomains();
+			for (uint i = 0; i < selections.size() && i < domains.size(); ++i) {
+				if (selections[i]) {
+					selectedDomains.push_back(domains[i]);
+				}
+			}
+
 			selectLauncher();
+
+			if (_impl && !selectedDomains.empty()) {
+				const Common::StringArray &newDomains = _impl->getDomains();
+				Common::Array<bool> &newSelections = const_cast<Common::Array<bool>&>(_impl->getSelectedItems());
+				for (const auto &domain : selectedDomains) {
+					for (uint i = 0; i < newDomains.size(); ++i) {
+						if (newDomains[i] == domain) {
+							if (i < newSelections.size())
+								newSelections[i] = true;
+							break;
+						}
+					}
+				}
+			}
 		}
 	} while (ret < -1);
 	return ret;
diff --git a/gui/launcher.h b/gui/launcher.h
index 427b6a8daf6..a56e6add26d 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -123,6 +123,8 @@ public:
 	void handleOtherEvent(const Common::Event &evt) override;
 	bool doGameDetection(const Common::Path &path);
 	Common::String getGameConfig(int item, Common::String key);
+	virtual const Common::Array<bool>& getSelectedItems() const = 0; // Get the selected items from the current view (list or grid)
+	const Common::StringArray& getDomains() const { return _domains; }
 protected:
 	EditTextWidget  *_searchWidget;
 #ifndef DISABLE_FANCY_THEMES
@@ -219,8 +221,6 @@ protected:
 	 */
 	bool hasAnySelection(const Common::Array<bool> &selectedItems) const;
 
-	// Get the selected items from the current view (list or grid).
-	virtual const Common::Array<bool>& getSelectedItems() const = 0;
 
 	/**
 	 * Handle "Edit game..." button.


Commit: 02e4a55c528d4db934d3348a56c90c9dc2cf068e
    https://github.com/scummvm/scummvm/commit/02e4a55c528d4db934d3348a56c90c9dc2cf068e
Author: Mohit Bankar (mohitbankar1212 at gmail.com)
Date: 2026-06-13T14:09:02+02:00

Commit Message:
GUI: Preserve launcher grid selections when changing grouping

Changed paths:
    gui/launcher.cpp


diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index ad1f4344124..dfca4a7d991 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -1730,7 +1730,7 @@ void LauncherGrid::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
 				}
 				++mode;
 			}
-			updateListing();
+			updateListing(kSelPosGroupingChange);
 		}
 		break;
 	}
@@ -1785,12 +1785,18 @@ void LauncherGrid::updateListing(int selPos) {
 
 	const int oldSel = _grid->getSelected();
 
+	Common::Array<bool> savedSelection;
+	const bool restoringGroupedSelection = (selPos == kSelPosGroupingChange);
+	if (restoringGroupedSelection)
+		savedSelection = _grid->getSelectedItems();
 	_grid->setEntryList(&gridList);
 	groupEntries(domainList);
 
-	if (_groupBy != kGroupByNone && selPos != -1) {
+	if (restoringGroupedSelection)
+		const_cast<Common::Array<bool>&>(_grid->getSelectedItems()) = savedSelection;
+	else if (_groupBy != kGroupByNone && selPos != -1)
 		_grid->setSelected(_grid->getNewSel(selPos));
-	} else if (oldSel < (int)gridList.size() && oldSel >= 0)
+	else if (oldSel < (int)gridList.size() && oldSel >= 0)
 		_grid->setSelected(oldSel);	// Restore the old selection
 	else if (oldSel != -1)
 		// Select the last entry if the list has been reduced


Commit: 09c15f36720fb60d81eb49d792a3ac598ec76bdf
    https://github.com/scummvm/scummvm/commit/09c15f36720fb60d81eb49d792a3ac598ec76bdf
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2026-06-13T15:25:32+02:00

Commit Message:
JANITORIAL: Remove trailing spaces

Changed paths:
    gui/animation/FluidScroll.cpp


diff --git a/gui/animation/FluidScroll.cpp b/gui/animation/FluidScroll.cpp
index 3605f0d3386..a1b677c90cb 100644
--- a/gui/animation/FluidScroll.cpp
+++ b/gui/animation/FluidScroll.cpp
@@ -67,7 +67,7 @@ float FluidScroller::VelocityTracker::calculateVelocity() const {
 	for (int i = 0; i < 4 && i < count - 1; ++i) {
 		int i1 = (index + kHistorySize - 1 - i) % kHistorySize; // current point
 		int i2 = (index + kHistorySize - 2 - i) % kHistorySize; // previous point
-		
+
 		uint32 dt = samples[i1].time - samples[i2].time;
 
 		if (dt > 0)
@@ -78,7 +78,7 @@ float FluidScroller::VelocityTracker::calculateVelocity() const {
 
 	if (validVelocities == 0)
 		return 0.0f;
-	
+
 	// Weighted average of historical velocities
 	float totalVelocity = 0.0f;
 	float totalWeight = 0.0f;
@@ -91,12 +91,12 @@ float FluidScroller::VelocityTracker::calculateVelocity() const {
 	return totalVelocity / totalWeight;
 }
 
-FluidScroller::FluidScroller() : 
-	_mode(kModeNone), 
-	_startTime(0), 
-	_scrollPosRaw(0.0f), 
-	_animationOffset(0.0f), 
-	_maxScroll(0.0f), 
+FluidScroller::FluidScroller() :
+	_mode(kModeNone),
+	_startTime(0),
+	_scrollPosRaw(0.0f),
+	_animationOffset(0.0f),
+	_maxScroll(0.0f),
 	_stepSize(1.0f),
 	_viewportHeight(0),
 	_lastWheelTime(0),
@@ -165,7 +165,7 @@ void FluidScroller::feedWheel(uint32 time, float deltaY) {
 	/*
 	 * Cap the duration to prevent extreme high/low velocity
 	 * Otherwise use the actual interval
-	 */ 
+	 */
 	uint32 effectiveDt = dt;
 	if (dt > 200)
 		effectiveDt = 200;
@@ -199,7 +199,7 @@ void FluidScroller::handleMouseWheel(int direction, float multiplier) {
 void FluidScroller::absorb(float velocity, float distance) {
 	_mode = kModeSpringBack;
 	_startTime = g_system->getMillis();
-	
+
 	_lambda = 2.0f * (float)M_PI / kDefaultSpringResponse;
 	_stretchDistance = distance;
 
@@ -273,7 +273,7 @@ float FluidScroller::getVisualPosition() const {
 		return -calculateRubberBandOffset(-_scrollPosRaw, rubberBandRange);
 	else if (_scrollPosRaw > _maxScroll)
 		return _maxScroll + calculateRubberBandOffset(_scrollPosRaw - _maxScroll, rubberBandRange);
-	
+
 	return _scrollPosRaw;
 }
 


Commit: a9e0481ffa4bdfcd4652c758b28da6bcd7eccfca
    https://github.com/scummvm/scummvm/commit/a9e0481ffa4bdfcd4652c758b28da6bcd7eccfca
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2026-06-13T15:26:02+02:00

Commit Message:
BASE: Enable kinetic scrolling by default

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 04e8182e085..c29d1eb09ac 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -402,7 +402,7 @@ void registerDefaults() {
 	ConfMan.registerDefault("gui_return_to_launcher_at_exit", false);
 	ConfMan.registerDefault("gui_launcher_chooser", "list");
 	ConfMan.registerDefault("grid_items_per_row", 4);
-	ConfMan.registerDefault("gui_kinetic_scrolling", false);
+	ConfMan.registerDefault("gui_kinetic_scrolling", true);
 	// Specify threshold for scanning directories in the launcher
 	// If number of game entries in scummvm.ini exceeds the specified
 	// number, then skip scanning. -1 = scan always


Commit: fba6cfd6e5cbab2e8cfc6f9b4b42d65f880cdb99
    https://github.com/scummvm/scummvm/commit/fba6cfd6e5cbab2e8cfc6f9b4b42d65f880cdb99
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2026-06-13T15:36:30+02:00

Commit Message:
GUI: Added kinetic scrolling checkbox to GUI Options. Bump theme version

Changed paths:
    gui/ThemeEngine.h
    gui/options.cpp
    gui/options.h
    gui/themes/common/highres_layout.stx
    gui/themes/common/lowres_layout.stx
    gui/themes/default.inc
    gui/themes/residualvm.zip
    gui/themes/residualvm/THEMERC
    gui/themes/scummclassic.zip
    gui/themes/scummclassic/THEMERC
    gui/themes/scummclassic/classic_layout.stx
    gui/themes/scummclassic/classic_layout_lowres.stx
    gui/themes/scummmodern.zip
    gui/themes/scummmodern/THEMERC
    gui/themes/scummremastered.zip
    gui/themes/scummremastered/THEMERC


diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 199d0f5984b..48d47c5d176 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -36,7 +36,7 @@
 #include "graphics/pixelformat.h"
 
 
-#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.9.22"
+#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.9.23"
 
 class OSystem;
 
diff --git a/gui/options.cpp b/gui/options.cpp
index 895a3aa1428..7b971f05ab1 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2186,6 +2186,8 @@ GlobalOptionsDialog::GlobalOptionsDialog(LauncherDialog *launcher)
 	_guiReturnToLauncherAtExit = nullptr;
 	_guiConfirmExit = nullptr;
 	_guiDisableBDFScaling = nullptr;
+	_guiKineticScrolling = nullptr;
+
 #ifdef USE_UPDATES
 	_updatesPopUpDesc = nullptr;
 	_updatesPopUp = nullptr;
@@ -2662,11 +2664,18 @@ void GlobalOptionsDialog::addGUIControls(GuiObject *boss, const Common::String &
 
 	_guiDisableBDFScaling = new CheckboxWidget(boss, prefix + "DisableBDFScaling",
 		_("Disable fixed font scaling"),
-		_("Do not upscale fixed size fonts in the GUI. This reduces artefacts on low resolution screens")
+		_("Do not upscale fixed size fonts in the GUI. This reduces artefacts on low resolution screens.")
 	);
 
 	_guiDisableBDFScaling->setState(ConfMan.getBool("gui_disable_fixed_font_scaling", _domain));
 
+	_guiKineticScrolling = new CheckboxWidget(boss, prefix + "KineticScrolling",
+		_("Enable kinetic scrolling in lists"),
+		_("Enable smooth, momentum-based scrolling in list widgets.")
+	);
+
+	_guiKineticScrolling->setState(ConfMan.getBool("gui_kinetic_scrolling", _domain));
+
 #ifdef USE_TRANSLATION
 	_guiLanguagePopUpDesc = new StaticTextWidget(boss, prefix + "GuiLanguagePopupDesc", _("GUI language:"), _("Language of ScummVM GUI"));
 	_guiLanguagePopUp = new PopUpWidget(boss, prefix + "GuiLanguagePopup");
@@ -3139,6 +3148,10 @@ void GlobalOptionsDialog::apply() {
 		ConfMan.setBool("gui_disable_fixed_font_scaling", _guiDisableBDFScaling->getState(), _domain);
 	}
 
+	if (_guiKineticScrolling) {
+		ConfMan.setBool("gui_kinetic_scrolling", _guiKineticScrolling->getState(), _domain);
+	}
+
 #ifdef USE_DISCORD
 	if (_discordRpcCheckbox) {
 		ConfMan.setBool("discord_rpc", _discordRpcCheckbox->getState(), _domain);
diff --git a/gui/options.h b/gui/options.h
index 37509a3d303..f9041f62cec 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -317,6 +317,7 @@ protected:
 	CheckboxWidget *_guiReturnToLauncherAtExit;
 	CheckboxWidget *_guiConfirmExit;
 	CheckboxWidget *_guiDisableBDFScaling;
+	CheckboxWidget *_guiKineticScrolling;
 
 	void addGUIControls(GuiObject *boss, const Common::String &prefix, bool lowres);
 
diff --git a/gui/themes/common/highres_layout.stx b/gui/themes/common/highres_layout.stx
index fd5d3359a5d..c8f8d872fd2 100644
--- a/gui/themes/common/highres_layout.stx
+++ b/gui/themes/common/highres_layout.stx
@@ -1165,6 +1165,11 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
+				<widget name = 'KineticScrolling'
+						type = 'Checkbox'
+				/>
+			</layout>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'UseSystemDialogs'
 						type = 'Checkbox'
diff --git a/gui/themes/common/lowres_layout.stx b/gui/themes/common/lowres_layout.stx
index aa47897d488..ae6311cebe3 100644
--- a/gui/themes/common/lowres_layout.stx
+++ b/gui/themes/common/lowres_layout.stx
@@ -995,6 +995,11 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' align = 'center'>
+				<widget name = 'KineticScrolling'
+						type = 'Checkbox'
+				/>
+			</layout>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' align = 'center'>
 				<widget name = 'UseSystemDialogs'
 						type = 'Checkbox'
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 00deb393158..49ef03e6c50 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -2201,6 +2201,11 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "/>"
 "</layout>"
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' align='center'>"
+"<widget name='KineticScrolling' "
+"type='Checkbox' "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' align='center'>"
 "<widget name='UseSystemDialogs' "
 "type='Checkbox' "
 "/>"
@@ -4662,6 +4667,11 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "/>"
 "</layout>"
 "<layout type='horizontal' padding='0,0,0,0' spacing='6' align='center'>"
+"<widget name='KineticScrolling' "
+"type='Checkbox' "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' align='center'>"
 "<widget name='UseSystemDialogs' "
 "type='Checkbox' "
 "/>"
diff --git a/gui/themes/residualvm.zip b/gui/themes/residualvm.zip
index 08d43e5f105..0d57f6e477a 100644
Binary files a/gui/themes/residualvm.zip and b/gui/themes/residualvm.zip differ
diff --git a/gui/themes/residualvm/THEMERC b/gui/themes/residualvm/THEMERC
index a89a97066f7..442f37e083e 100644
--- a/gui/themes/residualvm/THEMERC
+++ b/gui/themes/residualvm/THEMERC
@@ -1,3 +1,3 @@
-[SCUMMVM_STX0.9.22:ResidualVM Modern Theme Remastered:No Author]
+[SCUMMVM_STX0.9.23:ResidualVM Modern Theme Remastered:No Author]
 %using ../common
 %using ../common-svg
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 2f2df889c07..ca2607b382f 100644
Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ
diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC
index 433b25c75f0..d3a8ae3af49 100644
--- a/gui/themes/scummclassic/THEMERC
+++ b/gui/themes/scummclassic/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.9.22:ScummVM Classic Theme:No Author]
+[SCUMMVM_STX0.9.23:ScummVM Classic Theme:No Author]
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index abc6f9fd891..ceafccb9459 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -819,6 +819,11 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
+				<widget name = 'KineticScrolling'
+						type = 'Checkbox'
+				/>
+			</layout>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'UseSystemDialogs'
 						type = 'Checkbox'
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 8c93d4daf83..0fe3d149386 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -828,6 +828,11 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' align = 'center'>
+				<widget name = 'KineticScrolling'
+						type = 'Checkbox'
+				/>
+			</layout>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' align = 'center'>
 				<widget name = 'UseSystemDialogs'
 						type = 'Checkbox'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index b4a333f2f34..756addce923 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC
index a8ff598f81a..f56e57a3da9 100644
--- a/gui/themes/scummmodern/THEMERC
+++ b/gui/themes/scummmodern/THEMERC
@@ -1,2 +1,2 @@
-[SCUMMVM_STX0.9.22:ScummVM Modern Theme:No Author]
+[SCUMMVM_STX0.9.23:ScummVM Modern Theme:No Author]
 %using ../common
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index 5391be7e260..6abf823e5d5 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/THEMERC b/gui/themes/scummremastered/THEMERC
index 3c2b6baa640..2fffe8f54ca 100644
--- a/gui/themes/scummremastered/THEMERC
+++ b/gui/themes/scummremastered/THEMERC
@@ -1,3 +1,3 @@
-[SCUMMVM_STX0.9.22:ScummVM Modern Theme Remastered:No Author]
+[SCUMMVM_STX0.9.23:ScummVM Modern Theme Remastered:No Author]
 %using ../common
 %using ../common-svg




More information about the Scummvm-git-logs mailing list