mux: Fix mouse wheel cursor movement on remote alt screens

Track alternate screen state for panes connected to a mux domain. This
enables mouse wheel events to translate correctly to cursor movement
for alt screen applications.

closes: https://github.com/wezterm/wezterm/issues/4922
This commit is contained in:
Wez Furlong 2026-10-10 07:52:18 +01:00
parent 372548295b
commit e7280b8c88
No known key found for this signature in database
GPG Key ID: A7E93559F0040A51
4 changed files with 18 additions and 3 deletions

View File

@ -442,7 +442,7 @@ macro_rules! pdu {
/// The overall version of the codec.
/// This must be bumped when backwards incompatible changes
/// are made to the types and protocol.
pub const CODEC_VERSION: usize = 45;
pub const CODEC_VERSION: usize = 46;
// Defines the Pdu enum.
// Each struct has an explicit identifying number.
@ -915,6 +915,7 @@ pub struct LivenessResponse {
pub struct GetPaneRenderChangesResponse {
pub pane_id: PaneId,
pub mouse_grabbed: bool,
pub alt_screen_active: bool,
pub cursor_position: StableCursorPosition,
pub dimensions: RenderableDimensions,
pub dirty_lines: Vec<Range<StableRowIndex>>,

View File

@ -160,6 +160,10 @@ As features stabilize some brief notes about them will accumulate here.
`CTRL-u` to kill back to the start of the line. Thanks to @bew! #8013
#### Fixed
* Multiplexer: the mouse wheel was not mapped to cursor up/down keys in the
alternate screen for panes in a `wezterm connect` domain, because the client
always reported the alternate screen as inactive. The server now advises the
client of the alternate screen state. #4922
* macOS: Fix window border when opacity<1 and shadow enabled.
Thanks to @Adams-Galaxy! #8038 #5158
* perf: Terminal images were hashed three times each on the transmit path; the sha256

View File

@ -44,6 +44,7 @@ pub struct ClientPane {
mouse: Arc<Mutex<MouseState>>,
clipboard: Mutex<Option<Arc<dyn Clipboard>>>,
mouse_grabbed: Mutex<bool>,
alt_screen_active: Mutex<bool>,
ignore_next_kill: Mutex<bool>,
user_vars: Mutex<HashMap<String, String>>,
config: Mutex<Option<Arc<dyn TerminalConfiguration>>>,
@ -126,6 +127,7 @@ impl ClientPane {
palette: Mutex::new(palette),
clipboard: Mutex::new(None),
mouse_grabbed: Mutex::new(false),
alt_screen_active: Mutex::new(false),
ignore_next_kill: Mutex::new(false),
unseen_output: Mutex::new(false),
user_vars: Mutex::new(HashMap::new()),
@ -138,6 +140,7 @@ impl ClientPane {
match pdu {
Pdu::GetPaneRenderChangesResponse(mut delta) => {
*self.mouse_grabbed.lock() = delta.mouse_grabbed;
*self.alt_screen_active.lock() = delta.alt_screen_active;
let bonus_lines = std::mem::take(&mut delta.bonus_lines);
let client = { Arc::clone(&self.renderable.lock().inner.borrow().client) };
@ -546,8 +549,7 @@ impl Pane for ClientPane {
}
fn is_alt_screen_active(&self) -> bool {
// FIXME: retrieve this from the remote
false
*self.alt_screen_active.lock()
}
fn get_current_working_dir(&self, _policy: CachePolicy) -> Option<Url> {

View File

@ -42,6 +42,7 @@ pub(crate) struct PerPane {
working_dir: Option<Url>,
dimensions: RenderableDimensions,
mouse_grabbed: bool,
alt_screen_active: bool,
sent_initial_palette: bool,
seqno: SequenceNo,
config_generation: usize,
@ -60,6 +61,11 @@ impl PerPane {
changed = true;
}
let alt_screen_active = pane.is_alt_screen_active();
if alt_screen_active != self.alt_screen_active {
changed = true;
}
let dims = pane.get_dimensions();
if dims != self.dimensions {
changed = true;
@ -126,11 +132,13 @@ impl PerPane {
self.working_dir = working_dir.clone();
self.dimensions = dims;
self.mouse_grabbed = mouse_grabbed;
self.alt_screen_active = alt_screen_active;
let bonus_lines = bonus_lines.into();
Some(GetPaneRenderChangesResponse {
pane_id: pane.pane_id(),
mouse_grabbed,
alt_screen_active,
dirty_lines: all_dirty_lines.iter().cloned().collect(),
dimensions: dims,
cursor_position,