From a4681f0af522c4a2a5d27be71930559ae5a498f9 Mon Sep 17 00:00:00 2001
From: Sebastian Krzyszkowiak <dos@dosowisko.net>
Date: Sun, 10 Sep 2023 19:50:37 +0200
Subject: [PATCH] py,st3m: ScrollController: Improve safety checks around
 target position

Previously, target position could become an illegal value after calling
various methods until the next think call, so apps couldn't trust that
the received target position will be correct.

Make target position handling more robust and do boundary checks right
away whenever the value changes.
---
 python_payload/st3m/ui/interactions.py | 27 ++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/python_payload/st3m/ui/interactions.py b/python_payload/st3m/ui/interactions.py
index 4ee09f2236..55f20f43db 100644
--- a/python_payload/st3m/ui/interactions.py
+++ b/python_payload/st3m/ui/interactions.py
@@ -49,18 +49,25 @@ class ScrollController(st3m.Responder):
         if count < 0:
             count = 0
         self._nitems = count
-
-    def set_position(self, position: int) -> None:
-        """
-        Immediately set a position without animating the transition.
-        """
-        self._target_position = self._current_position = position
+        if self._target_position >= self._nitems:
+            self._target_position = self._nitems - 1
 
     def scroll_to(self, position: int) -> None:
         """
         Scroll to specified position.
         """
         self._target_position = position
+        if self._target_position < 0:
+            self._target_position = 0
+        if self._target_position >= self._nitems:
+            self._target_position = self._nitems - 1
+
+    def set_position(self, position: int) -> None:
+        """
+        Immediately set a position without animating the transition.
+        """
+        self.scroll_to(position)
+        self._current_position = self._target_position
 
     def scroll_left(self) -> None:
         """
@@ -69,6 +76,8 @@ class ScrollController(st3m.Responder):
         """
         self._target_position -= 1
         self._velocity = -10
+        if self._target_position < 0:
+            self._target_position = 0
 
     def scroll_right(self) -> None:
         """
@@ -77,6 +86,8 @@ class ScrollController(st3m.Responder):
         """
         self._target_position += 1
         self._velocity = 10
+        if self._target_position >= self._nitems:
+            self._target_position = self._nitems - 1
 
     def think(self, ins: InputState, delta_ms: int) -> None:
         if self._nitems == 0:
@@ -84,10 +95,6 @@ class ScrollController(st3m.Responder):
             self._current_position = 0
             self._velocity = 0
             return
-        if self._target_position < 0:
-            self._target_position = 0
-        if self._target_position >= self._nitems:
-            self._target_position = self._nitems - 1
 
         self._physics_step(min(delta_ms, 100) / 1000.0)
 
-- 
GitLab