aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--idatui/app.py19
-rw-r--r--tests/test_scenarios.py7
2 files changed, 24 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:
diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py
index 3401645..7d9f3b7 100644
--- a/tests/test_scenarios.py
+++ b/tests/test_scenarios.py
@@ -415,6 +415,13 @@ async def s_split_view(c: Ctx):
await c.pause(0.1)
c.check("Tab again focuses the listing pane", app._active == "listing",
f"active={app._active}")
+ # a mouse click on the other pane also makes it the driver (not just Tab)
+ await c.pilot.click(DecompView, offset=(10, 5))
+ await c.pause(0.15)
+ c.check("clicking the pseudocode pane makes it the driver",
+ app._active == "decomp", f"active={app._active}")
+ await c.press("tab") # restore listing as the driver
+ await c.pause(0.1)
# navigation in split keeps BOTH panes on the (new) function
nf = c.find_func(lambda f: f.addr != app._cur.ea and f.size > 80)
if nf is not None: