aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-25 18:59:43 +0200
committerblasty <blasty@local>2026-07-25 18:59:43 +0200
commitb2f221691f88af382c30b6a1d9060b75ea7c19dd (patch)
tree4f8fb8e264a28e30e4bfef3930f1dbded3add205
parentprojects: don't duplicate a binary that's already in the project (diff)
downloadida-tui-b2f221691f88af382c30b6a1d9060b75ea7c19dd.tar.gz
ida-tui-b2f221691f88af382c30b6a1d9060b75ea7c19dd.tar.xz
ida-tui-b2f221691f88af382c30b6a1d9060b75ea7c19dd.zip
decomp: repaint on a same-viewport jump (Esc back looked like it did nothing)
Esc in the pseudocode view navigated correctly but the pane kept showing the old cursor line until you pressed something else. The listing view was fine because its path goes through load(), which relayouts and repaints. DecompView.goto() sets `cursor`, which is reactive(repaint=False), and then leaves redrawing to _apply_scroll — but that only repaints via call_after_refresh, which needs a refresh to actually happen. Jump somewhere inside the viewport already on screen (exactly what Esc-back within a function does) and the scroll doesn't change, so nothing asked the widget to redraw: the old highlight stayed and the status line had already updated, which is why it looked like the jump half-worked. _move() doesn't hit this because it repaints the old and new rows via _refresh_lines. goto() now refreshes explicitly. Verification note: a render_line-level probe CANNOT see this bug — render_line reads self.cursor live, so it always reports the new position. The staleness is in Textual's compositor cache, which only a repaint request clears. Verified by spying on the widget's refresh instead: a same-viewport goto now requests one (it requested none before). Suite 192/0.
-rw-r--r--idatui/app.py7
1 files changed, 7 insertions, 0 deletions
diff --git a/idatui/app.py b/idatui/app.py
index e96483b..db237cb 100644
--- a/idatui/app.py
+++ b/idatui/app.py
@@ -1574,6 +1574,13 @@ class DecompView(SearchMixin, NavMixin, ColumnCursor, ScrollView, can_focus=True
else:
scroll_x = sx
self._apply_scroll(min(max(scroll_y, 0), max(total - 1, 0)), max(scroll_x, 0))
+ # `cursor` is reactive(repaint=False) and _apply_scroll only repaints via
+ # call_after_refresh, so a jump that lands in the SAME viewport (Esc back
+ # to another spot in the function already on screen) moved the cursor
+ # with nothing to redraw it — the pane kept showing the old highlight
+ # until the next keypress. Repaint here; _move does the same via
+ # _refresh_lines.
+ self.refresh()
self._after_cursor_move()
def get_loading_widget(self): # type: ignore[override]