1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-19 02:37:51 +03:00

mux protocol sending alerts to client

refs: https://github.com/wez/wezterm/issues/748
refs: https://github.com/wez/wezterm/issues/489
This commit is contained in:
Wez Furlong 2021-05-30 10:18:30 -07:00
parent f5f393bf2c
commit dc4c8f07dd
6 changed files with 116 additions and 21 deletions

View File

@ -30,7 +30,8 @@ use std::sync::Arc;
use termwiz::hyperlink::Hyperlink;
use termwiz::surface::Line;
use varbincode;
use wezterm_term::{ClipboardSelection, StableRowIndex};
use wezterm_term::color::ColorPalette;
use wezterm_term::{Alert, ClipboardSelection, StableRowIndex};
/// Returns the encoded length of the leb128 representation of value
fn encoded_length(value: u64) -> usize {
@ -400,7 +401,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 = 7;
pub const CODEC_VERSION: usize = 8;
// Defines the Pdu enum.
// Each struct has an explicit identifying number.
@ -437,6 +438,8 @@ pdu! {
KillPane: 35,
SpawnV2: 36,
PaneRemoved: 37,
SetPalette: 38,
NotifyAlert: 39,
}
impl Pdu {
@ -508,11 +511,11 @@ impl Pdu {
pub fn pane_id(&self) -> Option<PaneId> {
match self {
Pdu::GetPaneRenderChangesResponse(GetPaneRenderChangesResponse { pane_id, .. }) => {
Some(*pane_id)
}
Pdu::SetClipboard(SetClipboard { pane_id, .. }) => Some(*pane_id),
Pdu::PaneRemoved(PaneRemoved { pane_id }) => Some(*pane_id),
Pdu::GetPaneRenderChangesResponse(GetPaneRenderChangesResponse { pane_id, .. })
| Pdu::SetPalette(SetPalette { pane_id, .. })
| Pdu::NotifyAlert(NotifyAlert { pane_id, .. })
| Pdu::SetClipboard(SetClipboard { pane_id, .. })
| Pdu::PaneRemoved(PaneRemoved { pane_id }) => Some(*pane_id),
_ => None,
}
}
@ -675,6 +678,18 @@ pub struct SetClipboard {
pub selection: ClipboardSelection,
}
#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct SetPalette {
pub pane_id: PaneId,
pub palette: ColorPalette,
}
#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct NotifyAlert {
pub pane_id: PaneId,
pub alert: Alert,
}
#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct Resize {
pub containing_tab_id: TabId,

View File

@ -1,12 +1,38 @@
//! Colors for attributes
#[cfg(feature = "use_serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::result::Result;
pub use termwiz::color::{AnsiColor, ColorAttribute, RgbColor, RgbaTuple};
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
pub struct Palette256(pub [RgbColor; 256]);
#[cfg(feature = "use_serde")]
impl Serialize for Palette256 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_vec().serialize(serializer)
}
}
#[cfg(feature = "use_serde")]
impl<'de> Deserialize<'de> for Palette256 {
fn deserialize<D>(deserializer: D) -> Result<Palette256, D::Error>
where
D: Deserializer<'de>,
{
let s = Vec::<RgbColor>::deserialize(deserializer)?;
use std::convert::TryInto;
Ok(Self(s.try_into().map_err(|_| {
serde::de::Error::custom("Palette256 size mismatch")
})?))
}
}
impl std::iter::FromIterator<RgbColor> for Palette256 {
fn from_iter<I: IntoIterator<Item = RgbColor>>(iter: I) -> Self {
let mut colors = [RgbColor::default(); 256];
@ -17,7 +43,8 @@ impl std::iter::FromIterator<RgbColor> for Palette256 {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
pub struct ColorPalette {
pub colors: Palette256,
pub foreground: RgbColor,

View File

@ -37,6 +37,7 @@ pub trait DeviceControlHandler {
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
pub enum Alert {
Bell,
ToastNotification {

View File

@ -10,6 +10,7 @@ use mux::domain::DomainId;
use mux::pane::{alloc_pane_id, Pane, PaneId, Pattern, SearchResult};
use mux::renderable::{RenderableDimensions, StableCursorPosition};
use mux::tab::TabId;
use mux::{Mux, MuxNotification};
use portable_pty::PtySize;
use rangeset::RangeSet;
use ratelim::RateLimiter;
@ -21,7 +22,7 @@ use std::sync::Arc;
use termwiz::input::KeyEvent;
use url::Url;
use wezterm_term::color::ColorPalette;
use wezterm_term::{Clipboard, KeyCode, KeyModifiers, Line, MouseEvent, StableRowIndex};
use wezterm_term::{Alert, Clipboard, KeyCode, KeyModifiers, Line, MouseEvent, StableRowIndex};
pub struct ClientPane {
client: Arc<ClientInner>,
@ -29,6 +30,7 @@ pub struct ClientPane {
pub remote_pane_id: PaneId,
pub remote_tab_id: TabId,
pub renderable: RefCell<RenderableState>,
palette: RefCell<ColorPalette>,
writer: RefCell<PaneWriter>,
reader: Pipe,
mouse: Rc<RefCell<MouseState>>,
@ -76,6 +78,8 @@ impl ClientPane {
};
let reader = Pipe::new().expect("Pipe::new failed");
let config = configuration();
let palette: ColorPalette = config.resolved_palette.clone().into();
Self {
client: Arc::clone(client),
@ -85,6 +89,7 @@ impl ClientPane {
remote_tab_id,
renderable: RefCell::new(render),
writer: RefCell::new(writer),
palette: RefCell::new(palette),
reader,
clipboard: RefCell::new(None),
mouse_grabbed: RefCell::new(false),
@ -113,10 +118,25 @@ impl ClientPane {
log::error!("ClientPane: Ignoring SetClipboard request {:?}", clipboard);
}
},
Pdu::SetPalette(SetPalette { palette, .. }) => {
*self.palette.borrow_mut() = palette;
let mux = Mux::get().unwrap();
mux.notify(MuxNotification::Alert {
pane_id: self.local_pane_id,
alert: Alert::PaletteChanged,
});
}
Pdu::NotifyAlert(NotifyAlert { alert, .. }) => {
let mux = Mux::get().unwrap();
mux.notify(MuxNotification::Alert {
pane_id: self.local_pane_id,
alert,
});
}
Pdu::PaneRemoved(PaneRemoved { pane_id }) => {
log::trace!("remote pane {} has been removed", pane_id);
self.renderable.borrow().inner.borrow_mut().dead = true;
let mux = mux::Mux::get().unwrap();
let mux = Mux::get().unwrap();
mux.prune_dead_windows();
}
_ => bail!("unhandled unilateral pdu: {:?}", pdu),
@ -333,13 +353,10 @@ impl Pane for ClientPane {
fn palette(&self) -> ColorPalette {
let tardy = self.renderable.borrow().inner.borrow().is_tardy();
let config = configuration();
let palette: ColorPalette = config.resolved_palette.clone().into();
if tardy {
palette.grey_out()
self.palette.borrow().grey_out()
} else {
palette
self.palette.borrow().clone()
}
}

View File

@ -87,8 +87,12 @@ where
.await?;
stream.flush().await.context("flushing PDU to client")?;
}
Ok(Item::Notif(MuxNotification::Alert { pane_id, alert: _ })) => {
// FIXME: queue notification to send to client!
Ok(Item::Notif(MuxNotification::Alert { pane_id, alert })) => {
{
let per_pane = handler.per_pane(pane_id);
let mut per_pane = per_pane.lock().unwrap();
per_pane.notifications.push(alert);
}
handler.schedule_pane_push(pane_id);
}
Ok(Item::Notif(MuxNotification::WindowCreated(_window_id))) => {}

View File

@ -15,7 +15,7 @@ use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use url::Url;
use wezterm_term::terminal::{Clipboard, ClipboardSelection};
use wezterm_term::terminal::{Alert, Clipboard, ClipboardSelection};
use wezterm_term::StableRowIndex;
#[derive(Clone)]
@ -37,13 +37,15 @@ impl PduSender {
}
#[derive(Default, Debug)]
struct PerPane {
pub(crate) struct PerPane {
cursor_position: StableCursorPosition,
title: String,
working_dir: Option<Url>,
dimensions: RenderableDimensions,
dirty_lines: RangeSet<StableRowIndex>,
mouse_grabbed: bool,
sent_initial_palette: bool,
pub(crate) notifications: Vec<Alert>,
}
impl PerPane {
@ -148,6 +150,32 @@ fn maybe_push_pane_changes(
serial: 0,
})?;
}
if !per_pane.sent_initial_palette {
per_pane.notifications.push(Alert::PaletteChanged);
per_pane.sent_initial_palette = true;
}
for alert in per_pane.notifications.drain(..) {
match alert {
Alert::PaletteChanged => {
sender.send(DecodedPdu {
pdu: Pdu::SetPalette(SetPalette {
pane_id: pane.pane_id(),
palette: pane.palette(),
}),
serial: 0,
})?;
}
alert => {
sender.send(DecodedPdu {
pdu: Pdu::NotifyAlert(NotifyAlert {
pane_id: pane.pane_id(),
alert,
}),
serial: 0,
})?;
}
}
}
Ok(())
}
@ -174,7 +202,8 @@ impl SessionHandler {
per_pane: HashMap::new(),
}
}
fn per_pane(&mut self, pane_id: PaneId) -> Arc<Mutex<PerPane>> {
pub(crate) fn per_pane(&mut self, pane_id: PaneId) -> Arc<Mutex<PerPane>> {
Arc::clone(
self.per_pane
.entry(pane_id)
@ -535,6 +564,8 @@ impl SessionHandler {
Pdu::Pong { .. }
| Pdu::ListPanesResponse { .. }
| Pdu::SetClipboard { .. }
| Pdu::NotifyAlert { .. }
| Pdu::SetPalette { .. }
| Pdu::SpawnResponse { .. }
| Pdu::GetPaneRenderChangesResponse { .. }
| Pdu::UnitResponse { .. }