aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-03-31 23:22:40 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-03-31 23:22:40 +0300
commit85945c56a56c0a4acd948c83b50ea6ab10b9930c (patch)
tree84ce6070822256d5a0c72a893f7e4f7cb78e5ab5
parente857710d73ad660d17ce39fa3201a39aa49f6932 (diff)
test: cover non-top-anchored scroll regions
-rw-r--r--CHANGELOG.md8
-rw-r--r--src/pane.rs66
2 files changed, 53 insertions, 21 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index db7d1ec0..8f6a8390 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
## Unreleased
+### Changed
+- Mouse wheel handling now follows the tmux/Ghostty model more closely: fullscreen apps receive wheel input when they own scrolling, while herdr keeps host scrollback for panes that are behaving like a normal terminal transcript.
+- Pane scrollbars now only appear when herdr has real host scrollback for that pane, instead of implying a host-managed scroll position for app-owned scrolling.
+
+### Fixed
+- Fixed Codex and pi panes becoming unscrollable in herdr by preserving recoverable host history for top-anchored normal-screen output, without relying on alternate-screen scrollback retention.
+- Fixed pane wheel routing so apps using mouse reporting or alternate-scroll behavior can receive scroll input directly instead of having herdr always intercept it.
+
## [0.2.2] - 2026-03-31
### Fixed
diff --git a/src/pane.rs b/src/pane.rs
index 01d872a6..44238a8a 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -416,28 +416,52 @@ impl PaneRuntime {
last_process_check = now;
let pid = child_pid.load(Ordering::Acquire);
if pid > 0 {
- if let Some(job) = detect::foreground_job(pid) {
- let identified = detect::identify_agent_in_job(&job);
- let new_agent = identified.as_ref().map(|(agent, _)| *agent);
- if new_agent != agent {
- if let Some((_, process_name)) = identified {
- info!(
- pane = pane_id.raw(),
- ?new_agent,
- process = %process_name,
- pgid = job.process_group_id,
- "agent changed"
- );
- } else {
- info!(
- pane = pane_id.raw(),
- ?new_agent,
- pgid = job.process_group_id,
- "agent changed"
- );
+ match detect::foreground_job(pid) {
+ Some(job) => {
+ let identified = detect::identify_agent_in_job(&job);
+ let new_agent = identified.as_ref().map(|(agent, _)| *agent);
+
+ debug!(
+ pane = pane_id.raw(),
+ pid,
+ previous_agent = ?agent,
+ ?new_agent,
+ identified_process = identified
+ .as_ref()
+ .map(|(_, name)| name.as_str()),
+ pgid = job.process_group_id,
+ processes = ?job.processes,
+ "foreground job probe"
+ );
+
+ if new_agent != agent {
+ if let Some((_, process_name)) = identified {
+ info!(
+ pane = pane_id.raw(),
+ ?new_agent,
+ process = %process_name,
+ pgid = job.process_group_id,
+ "agent changed"
+ );
+ } else {
+ info!(
+ pane = pane_id.raw(),
+ ?new_agent,
+ pgid = job.process_group_id,
+ "agent changed"
+ );
+ }
+ agent = new_agent;
+ agent_changed = true;
}
- agent = new_agent;
- agent_changed = true;
+ }
+ None => {
+ debug!(
+ pane = pane_id.raw(),
+ pid,
+ previous_agent = ?agent,
+ "foreground job probe returned none"
+ );
}
}
}