aboutsummaryrefslogtreecommitdiffstats
path: root/idatui
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-25 00:10:30 +0200
committerblasty <blasty@local>2026-07-25 00:10:30 +0200
commitec6594e9d8b147df0aaff67752c5b85a55c0971d (patch)
tree8a855dc8831ae536a1653ed4cf601fc8effea884 /idatui
parentsplit-view phase 4: split-aware status, min-width gate, verified nav (diff)
downloadida-tui-ec6594e9d8b147df0aaff67752c5b85a55c0971d.tar.gz
ida-tui-ec6594e9d8b147df0aaff67752c5b85a55c0971d.tar.xz
ida-tui-ec6594e9d8b147df0aaff67752c5b85a55c0971d.zip
split: click a pane to drive it (not just Tab) + spell it out in the status
The sync direction follows the FOCUSED pane, but that was only discoverable via Tab. Add on_descendant_focus: in split, focusing a pane (Tab or a mouse click) makes it the leading/driver pane and re-syncs — so clicking into the pseudocode and cursoring around now drives the listing, matching intuition (previously a click focused the widget but left _active — and thus the sync direction — pointing at the other pane). The split status now ends with "(Tab/click: drive <other pane>)" so it's obvious. Pilot split_view: clicking the pseudocode pane makes it the driver (17/17).
Diffstat (limited to 'idatui')
-rw-r--r--idatui/app.py19
1 files changed, 17 insertions, 2 deletions
diff --git a/idatui/app.py b/idatui/app.py
index 0d4ae6a..66d1b44 100644
--- a/idatui/app.py
+++ b/idatui/app.py
@@ -4626,11 +4626,26 @@ class IdaTui(App):
at = f" @ {ea:#x}" if ea is not None else ""
rel = f" \u2194 {n} insn" if n else ""
self._status(f"{self._cur.name}{at} "
- f"[split \u00b7 pseudocode line {dec.cursor + 1}{rel}]")
+ f"[split \u00b7 pseudocode line {dec.cursor + 1}{rel}]"
+ f" (Tab/click: drive listing)")
else:
ea = self.query_one(ListingView)._cursor_ea()
at = f" @ {ea:#x}" if ea is not None else ""
- self._status(f"{self._cur.name}{at} [split \u00b7 listing]")
+ self._status(f"{self._cur.name}{at} [split \u00b7 listing]"
+ f" (Tab/click: drive pseudocode)")
+
+ def on_descendant_focus(self, event) -> None: # type: ignore[no-untyped-def]
+ """In split, focusing a pane (Tab or a mouse click) makes it the leading/
+ driver pane, so the sync direction follows where you're actually working."""
+ if not self._split:
+ return
+ w = event.control
+ new = ("decomp" if isinstance(w, DecompView)
+ else "listing" if isinstance(w, ListingView) else None)
+ if new is not None and new != self._active:
+ self._active = new
+ self._sync_split(new)
+ self._split_status()
@work(thread=True, group="split-map")
def _load_split_map(self, ea: int) -> None: