aboutsummaryrefslogtreecommitdiffstats
path: root/idatui
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-24 15:48:19 +0200
committerblasty <blasty@local>2026-07-24 15:48:19 +0200
commit4975a92c338819b43cb6647d7bbb9197c5772f32 (patch)
treed36a08551940cc25643bab5867d741e1862e8007 /idatui
parenthex: click to place the byte cursor (hex + ascii panes) (diff)
downloadida-tui-4975a92c338819b43cb6647d7bbb9197c5772f32.tar.gz
ida-tui-4975a92c338819b43cb6647d7bbb9197c5772f32.tar.xz
ida-tui-4975a92c338819b43cb6647d7bbb9197c5772f32.zip
hex: cursor follows the scroll (stays visible on wheel/scrollbar)
Override watch_scroll_y so a viewport scroll drags the byte cursor along: when the rounded scroll changes, clamp the cursor's row into the visible range [top, top+height) keeping its column, so it rides the nearest edge instead of being left off-screen. No feedback loop -- key-nav's _scroll_to_cursor already puts the cursor in view (clamp is then a no-op), and HexView.Moved only updates the status line. Pairs with the click-to-place support. Pilot `hex` scenario updated: after a scroll the cursor must now be within the visible rows (was: asserted it stayed put). 9/9 hex checks pass.
Diffstat (limited to 'idatui')
-rw-r--r--idatui/app.py20
1 files changed, 20 insertions, 0 deletions
diff --git a/idatui/app.py b/idatui/app.py
index 5314f66..3b84217 100644
--- a/idatui/app.py
+++ b/idatui/app.py
@@ -1680,6 +1680,26 @@ class HexView(ScrollView, can_focus=True):
top = max(0, min(top, max(self.total - 1, 0)))
self._apply_scroll(top)
+ def watch_scroll_y(self, old_value: float, new_value: float) -> None:
+ super().watch_scroll_y(old_value, new_value)
+ # Follow the scroll: a wheel-scroll / scrollbar drag drags the byte cursor
+ # along so it stays visible (pinned to the nearest edge row, same column).
+ if round(old_value) != round(new_value):
+ self._follow_scroll(round(new_value))
+
+ def _follow_scroll(self, top: int) -> None:
+ if self.model is None or self.model.size == 0:
+ return
+ height = self._visible_height()
+ row, col = self.cursor // 16, self.cursor % 16
+ new_row = min(max(row, top), top + max(height - 1, 0))
+ new_row = max(0, min(new_row, max(self.total - 1, 0)))
+ new_cursor = max(0, min(new_row * 16 + col, self.model.size - 1))
+ if new_cursor != self.cursor:
+ self.cursor = new_cursor
+ self.refresh() # cursor is reactive(repaint=False)
+ self.post_message(HexView.Moved(self.cursor_va()))
+
# -- navigation -------------------------------------------------------- #
def _move(self, delta: int) -> None:
if self.model is None or self.model.size == 0: