Skip to content

Commit

Permalink
mux: propagate pane focus change events to clients
Browse files Browse the repository at this point in the history
This commit causes the mux to generate a PaneFocused notification
when the active pane is changed.

The mux server will forward that as a unilateral PDU to connected
clients.

The clientpane implementation will handle that by applying the
same state to the local mux.

refs: #2863
  • Loading branch information
wez committed Mar 24, 2023
1 parent 75cdb21 commit f71bce1
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 1 deletion.
9 changes: 8 additions & 1 deletion codec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,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 = 33;
pub const CODEC_VERSION: usize = 34;

// Defines the Pdu enum.
// Each struct has an explicit identifying number.
Expand Down Expand Up @@ -468,6 +468,7 @@ pdu! {
ActivatePaneDirection: 50,
GetPaneRenderableDimensions: 51,
GetPaneRenderableDimensionsResponse: 52,
PaneFocused: 53,
}

impl Pdu {
Expand Down Expand Up @@ -543,6 +544,7 @@ impl Pdu {
| Pdu::SetPalette(SetPalette { pane_id, .. })
| Pdu::NotifyAlert(NotifyAlert { pane_id, .. })
| Pdu::SetClipboard(SetClipboard { pane_id, .. })
| Pdu::PaneFocused(PaneFocused { pane_id })
| Pdu::PaneRemoved(PaneRemoved { pane_id }) => Some(*pane_id),
_ => None,
}
Expand Down Expand Up @@ -733,6 +735,11 @@ pub struct NotifyAlert {
pub alert: Alert,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct PaneFocused {
pub pane_id: PaneId,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct WindowWorkspaceChanged {
pub window_id: WindowId,
Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ As features stabilize some brief notes about them will accumulate here.
* macos: command line parameters beyond the first were treated as terminal
command scripts and opened spurious windows. #3340
* imgcat broken with multiplexer protocol #3343
* `wezterm cli activate-pane-direction` would not cause the focus to change
in the GUI when explicitly using multiplexing domains. #2863

### 20230320-124340-559cb7b0

Expand Down
1 change: 1 addition & 0 deletions mux/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub enum MuxNotification {
tab_id: TabId,
window_id: WindowId,
},
PaneFocused(PaneId),
}

static SUB_ID: AtomicUsize = AtomicUsize::new(0);
Expand Down
3 changes: 3 additions & 0 deletions mux/src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1715,14 +1715,17 @@ impl TabInner {
}

fn advise_focus_change(&mut self, prior: Option<Arc<dyn Pane>>) {
let mux = Mux::get();
let current = self.get_active_pane();
match (prior, current) {
(Some(prior), Some(current)) if prior.pane_id() != current.pane_id() => {
prior.focus_changed(false);
current.focus_changed(true);
mux.notify(MuxNotification::PaneFocused(current.pane_id()));
}
(None, Some(current)) => {
current.focus_changed(true);
mux.notify(MuxNotification::PaneFocused(current.pane_id()));
}
(Some(prior), None) => {
prior.focus_changed(false);
Expand Down
39 changes: 39 additions & 0 deletions wezterm-client/src/pane/clientpane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,45 @@ impl ClientPane {

self.client.expire_stale_mappings();
}
Pdu::PaneFocused(PaneFocused { pane_id }) => {
// We get here whenever the pane focus is changed on the
// server. That might be due to the user here in the GUI
// doing things, or it may be due to a "remote"
// `wezterm cli activate-pane-direction` or similar call
// from some other actor.
// The latter case is the important one: it is desirable
// for the focus change to be reflected locally after it
// has been changed on the server, so we work to apply
// it here.
log::trace!("advised of remote pane focus: {pane_id}");

let mux = Mux::get();
let (_domain, window_id, tab_id) = mux
.resolve_pane_id(self.local_pane_id)
.ok_or_else(|| anyhow::anyhow!("can't find myself in the mux"))?;

// Focus/activate the containing tab within its window
{
let mut win = mux
.get_window_mut(window_id)
.ok_or_else(|| anyhow::anyhow!("window_id {window_id} not found"))?;
let tab_idx = win
.idx_by_id(tab_id)
.ok_or_else(|| anyhow::anyhow!("tab {tab_id} not in {window_id}"))?;
win.save_and_then_set_active(tab_idx);
}

// Focus/activate the pane locally
let tab = mux
.get_tab(tab_id)
.ok_or_else(|| anyhow::anyhow!("tab {tab_id} not found"))?;

let pane = mux.get_pane(self.local_pane_id).ok_or_else(|| {
anyhow::anyhow!("pane {} not found. That's me?", self.local_pane_id)
})?;

tab.set_active_pane(&pane);
}
_ => bail!("unhandled unilateral pdu: {:?}", pdu),
};
Ok(())
Expand Down
1 change: 1 addition & 0 deletions wezterm-gui/src/frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ impl GuiFrontEnd {
})
.detach();
}
MuxNotification::PaneFocused(_) => {}
MuxNotification::TabAddedToWindow { .. } => {}
MuxNotification::PaneRemoved(_) => {}
MuxNotification::WindowInvalidated(_) => {}
Expand Down
4 changes: 4 additions & 0 deletions wezterm-gui/src/termwindow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,9 @@ impl TermWindow {
MuxNotification::SaveToDownloads { .. } => {
// Handled by frontend
}
MuxNotification::PaneFocused(_) => {
// Handled by frontend
}
MuxNotification::PaneAdded(_)
| MuxNotification::PaneRemoved(_)
| MuxNotification::WindowWorkspaceChanged(_)
Expand Down Expand Up @@ -1345,6 +1348,7 @@ impl TermWindow {
}
| MuxNotification::AssignClipboard { .. }
| MuxNotification::SaveToDownloads { .. }
| MuxNotification::PaneFocused(_)
| MuxNotification::PaneRemoved(_)
| MuxNotification::WindowCreated(_)
| MuxNotification::ActiveWorkspaceChanged(_)
Expand Down
6 changes: 6 additions & 0 deletions wezterm-mux-server-impl/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ where
stream.flush().await.context("flushing PDU to client")?;
}
}
Ok(Item::Notif(MuxNotification::PaneFocused(pane_id))) => {
Pdu::PaneFocused(codec::PaneFocused { pane_id })
.encode_async(&mut stream, 0)
.await?;
stream.flush().await.context("flushing PDU to client")?;
}
Ok(Item::Notif(MuxNotification::ActiveWorkspaceChanged(_))) => {}
Ok(Item::Notif(MuxNotification::Empty)) => {}
Err(err) => {
Expand Down
2 changes: 2 additions & 0 deletions wezterm-mux-server-impl/src/sessionhandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ impl SessionHandler {
let mux = Mux::get();
let _identity = mux.with_identity(client_id);
mux.record_focus_for_current_identity(pane_id);
mux.notify(mux::MuxNotification::PaneFocused(pane_id));
})
.detach();
send_response(Ok(Pdu::UnitResponse(UnitResponse {})))
Expand Down Expand Up @@ -746,6 +747,7 @@ impl SessionHandler {
| Pdu::GetTlsCredsResponse { .. }
| Pdu::GetClientListResponse { .. }
| Pdu::PaneRemoved { .. }
| Pdu::PaneFocused { .. }
| Pdu::GetImageCellResponse { .. }
| Pdu::MovePaneToNewTabResponse { .. }
| Pdu::GetPaneRenderableDimensionsResponse { .. }
Expand Down

0 comments on commit f71bce1

Please sign in to comment.