Skip to content

Commit

Permalink
fix(sixel): report pixel size in winsize change ioctl (zellij-org#2212)
Browse files Browse the repository at this point in the history
* fix(sixel): report pixel size in winsize change ioctl

* style(fmt): rustfmt
  • Loading branch information
imsnif committed Mar 1, 2023
1 parent 73603c9 commit 1e13076
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 44 deletions.
50 changes: 40 additions & 10 deletions zellij-server/src/os_input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,24 @@ use std::{
pub use async_trait::async_trait;
pub use nix::unistd::Pid;

fn set_terminal_size_using_fd(fd: RawFd, columns: u16, rows: u16) {
fn set_terminal_size_using_fd(
fd: RawFd,
columns: u16,
rows: u16,
width_in_pixels: Option<u16>,
height_in_pixels: Option<u16>,
) {
// TODO: do this with the nix ioctl
use libc::ioctl;
use libc::TIOCSWINSZ;

let ws_xpixel = width_in_pixels.unwrap_or(0);
let ws_ypixel = height_in_pixels.unwrap_or(0);
let winsize = Winsize {
ws_col: columns,
ws_row: rows,
ws_xpixel: 0,
ws_ypixel: 0,
ws_xpixel,
ws_ypixel,
};
// TIOCGWINSZ is an u32, but the second argument to ioctl is u64 on
// some platforms. When checked on Linux, clippy will complain about
Expand Down Expand Up @@ -414,7 +422,7 @@ pub struct ServerOsInputOutput {
// not connected to an fd (eg.
// a command pane with a
// non-existing command)
cached_resizes: Arc<Mutex<Option<BTreeMap<u32, (u16, u16)>>>>, // <terminal_id, (cols, rows)>
cached_resizes: Arc<Mutex<Option<BTreeMap<u32, (u16, u16, Option<u16>, Option<u16>)>>>>, // <terminal_id, (cols, rows, width_in_pixels, height_in_pixels)>
}

// async fn in traits is not supported by rust, so dtolnay's excellent async_trait macro is being
Expand Down Expand Up @@ -448,7 +456,14 @@ impl AsyncReader for RawFdAsyncReader {
/// The `ServerOsApi` trait represents an abstract interface to the features of an operating system that
/// Zellij server requires.
pub trait ServerOsApi: Send + Sync {
fn set_terminal_size_using_terminal_id(&self, id: u32, cols: u16, rows: u16) -> Result<()>;
fn set_terminal_size_using_terminal_id(
&self,
id: u32,
cols: u16,
rows: u16,
width_in_pixels: Option<u16>,
height_in_pixels: Option<u16>,
) -> Result<()>;
/// Spawn a new terminal, with a terminal action. The returned tuple contains the master file
/// descriptor of the forked pseudo terminal and a [ChildId] struct containing process id's for
/// the forked child process.
Expand Down Expand Up @@ -501,15 +516,22 @@ pub trait ServerOsApi: Send + Sync {
}

impl ServerOsApi for ServerOsInputOutput {
fn set_terminal_size_using_terminal_id(&self, id: u32, cols: u16, rows: u16) -> Result<()> {
fn set_terminal_size_using_terminal_id(
&self,
id: u32,
cols: u16,
rows: u16,
width_in_pixels: Option<u16>,
height_in_pixels: Option<u16>,
) -> Result<()> {
let err_context = || {
format!(
"failed to set terminal id {} to size ({}, {})",
id, rows, cols
)
};
if let Some(cached_resizes) = self.cached_resizes.lock().unwrap().as_mut() {
cached_resizes.insert(id, (cols, rows));
cached_resizes.insert(id, (cols, rows, width_in_pixels, height_in_pixels));
return Ok(());
}

Expand All @@ -522,7 +544,7 @@ impl ServerOsApi for ServerOsInputOutput {
{
Some(Some(fd)) => {
if cols > 0 && rows > 0 {
set_terminal_size_using_fd(*fd, cols, rows);
set_terminal_size_using_fd(*fd, cols, rows, width_in_pixels, height_in_pixels);
}
},
_ => {
Expand Down Expand Up @@ -785,8 +807,16 @@ impl ServerOsApi for ServerOsInputOutput {
fn apply_cached_resizes(&mut self) {
let mut cached_resizes = self.cached_resizes.lock().unwrap().take();
if let Some(cached_resizes) = cached_resizes.as_mut() {
for (terminal_id, (cols, rows)) in cached_resizes.iter() {
let _ = self.set_terminal_size_using_terminal_id(*terminal_id, *cols, *rows);
for (terminal_id, (cols, rows, width_in_pixels, height_in_pixels)) in
cached_resizes.iter()
{
let _ = self.set_terminal_size_using_terminal_id(
*terminal_id,
*cols,
*rows,
width_in_pixels.clone(),
height_in_pixels.clone(),
);
}
}
}
Expand Down
23 changes: 17 additions & 6 deletions zellij-server/src/panes/floating_panes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use zellij_utils::{
errors::prelude::*,
input::command::RunCommand,
input::layout::FloatingPaneLayout,
pane_size::{Dimension, Offset, PaneGeom, Size, Viewport},
pane_size::{Dimension, Offset, PaneGeom, Size, SizeInPixels, Viewport},
};

const RESIZE_INCREMENT_WIDTH: usize = 5;
Expand All @@ -39,6 +39,7 @@ pub struct FloatingPanes {
connected_clients: Rc<RefCell<HashSet<ClientId>>>,
connected_clients_in_app: Rc<RefCell<HashSet<ClientId>>>,
mode_info: Rc<RefCell<HashMap<ClientId, ModeInfo>>>,
character_cell_size: Rc<RefCell<Option<SizeInPixels>>>,
default_mode_info: ModeInfo,
style: Style,
session_is_mirrored: bool,
Expand All @@ -59,6 +60,7 @@ impl FloatingPanes {
connected_clients: Rc<RefCell<HashSet<ClientId>>>,
connected_clients_in_app: Rc<RefCell<HashSet<ClientId>>>,
mode_info: Rc<RefCell<HashMap<ClientId, ModeInfo>>>,
character_cell_size: Rc<RefCell<Option<SizeInPixels>>>,
session_is_mirrored: bool,
default_mode_info: ModeInfo,
style: Style,
Expand All @@ -72,6 +74,7 @@ impl FloatingPanes {
connected_clients,
connected_clients_in_app,
mode_info,
character_cell_size,
session_is_mirrored,
default_mode_info,
style,
Expand Down Expand Up @@ -304,7 +307,8 @@ impl FloatingPanes {
} else {
pane.set_content_offset(Offset::default());
}
resize_pty!(pane, os_api, self.senders).with_context(|| err_context(&pane.pid()))?;
resize_pty!(pane, os_api, self.senders, self.character_cell_size)
.with_context(|| err_context(&pane.pid()))?;
}
Ok(())
}
Expand Down Expand Up @@ -390,7 +394,7 @@ impl FloatingPanes {

pub fn resize_pty_all_panes(&mut self, os_api: &mut Box<dyn ServerOsApi>) -> Result<()> {
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders)
resize_pty!(pane, os_api, self.senders, self.character_cell_size)
.with_context(|| format!("failed to resize PTY in pane {:?}", pane.pid()))?;
}
Ok(())
Expand Down Expand Up @@ -424,7 +428,8 @@ impl FloatingPanes {
.with_context(err_context)?;

for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).with_context(err_context)?;
resize_pty!(pane, os_api, self.senders, self.character_cell_size)
.with_context(err_context)?;
}
self.set_force_render();
return Ok(true);
Expand Down Expand Up @@ -833,15 +838,21 @@ impl FloatingPanes {
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
resize_pty!(new_position, os_api, self.senders).unwrap();
resize_pty!(new_position, os_api, self.senders, self.character_cell_size).unwrap();
new_position.set_should_render(true);

let current_position = self.panes.get_mut(&active_pane_id).unwrap();
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
}
resize_pty!(current_position, os_api, self.senders).unwrap();
resize_pty!(
current_position,
os_api,
self.senders,
self.character_cell_size
)
.unwrap();
current_position.set_should_render(true);
self.focus_pane_for_all_clients(active_pane_id);
}
Expand Down
100 changes: 86 additions & 14 deletions zellij-server/src/panes/tiled_panes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ impl TiledPanes {
}
}

resize_pty!(pane, self.os_api, self.senders).unwrap();
resize_pty!(pane, self.os_api, self.senders, self.character_cell_size).unwrap();
}
self.reset_boundaries();
}
Expand Down Expand Up @@ -781,7 +781,7 @@ impl TiledPanes {
}

for pane in self.panes.values_mut() {
resize_pty!(pane, self.os_api, self.senders).unwrap();
resize_pty!(pane, self.os_api, self.senders, self.character_cell_size).unwrap();
}
self.reset_boundaries();
}
Expand Down Expand Up @@ -1071,15 +1071,27 @@ impl TiledPanes {
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
resize_pty!(new_position, self.os_api, self.senders).unwrap();
resize_pty!(
new_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
new_position.set_should_render(true);

let current_position = self.panes.get_mut(&active_pane_id).unwrap();
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
}
resize_pty!(current_position, self.os_api, self.senders).unwrap();
resize_pty!(
current_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
current_position.set_should_render(true);
self.focus_pane_for_all_clients(active_pane_id);
self.set_pane_frames(self.draw_pane_frames);
Expand Down Expand Up @@ -1123,15 +1135,27 @@ impl TiledPanes {
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
resize_pty!(new_position, self.os_api, self.senders).unwrap();
resize_pty!(
new_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
new_position.set_should_render(true);

let current_position = self.panes.get_mut(&active_pane_id).unwrap();
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
}
resize_pty!(current_position, self.os_api, self.senders).unwrap();
resize_pty!(
current_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
current_position.set_should_render(true);
self.set_pane_frames(self.draw_pane_frames);
}
Expand Down Expand Up @@ -1159,15 +1183,27 @@ impl TiledPanes {
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
resize_pty!(new_position, self.os_api, self.senders).unwrap();
resize_pty!(
new_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
new_position.set_should_render(true);

let current_position = self.panes.get_mut(active_pane_id).unwrap();
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
}
resize_pty!(current_position, self.os_api, self.senders).unwrap();
resize_pty!(
current_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
current_position.set_should_render(true);
self.set_pane_frames(self.draw_pane_frames);
}
Expand Down Expand Up @@ -1195,15 +1231,27 @@ impl TiledPanes {
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
resize_pty!(new_position, self.os_api, self.senders).unwrap();
resize_pty!(
new_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
new_position.set_should_render(true);

let current_position = self.panes.get_mut(active_pane_id).unwrap();
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
}
resize_pty!(current_position, self.os_api, self.senders).unwrap();
resize_pty!(
current_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
current_position.set_should_render(true);
self.set_pane_frames(self.draw_pane_frames);
}
Expand Down Expand Up @@ -1231,15 +1279,27 @@ impl TiledPanes {
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
resize_pty!(new_position, self.os_api, self.senders).unwrap();
resize_pty!(
new_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
new_position.set_should_render(true);

let current_position = self.panes.get_mut(active_pane_id).unwrap();
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
}
resize_pty!(current_position, self.os_api, self.senders).unwrap();
resize_pty!(
current_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
current_position.set_should_render(true);
self.set_pane_frames(self.draw_pane_frames);
}
Expand Down Expand Up @@ -1269,15 +1329,27 @@ impl TiledPanes {
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
resize_pty!(new_position, self.os_api, self.senders).unwrap();
resize_pty!(
new_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
new_position.set_should_render(true);

let current_position = self.panes.get_mut(active_pane_id).unwrap();
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
}
resize_pty!(current_position, self.os_api, self.senders).unwrap();
resize_pty!(
current_position,
self.os_api,
self.senders,
self.character_cell_size
)
.unwrap();
current_position.set_should_render(true);
self.set_pane_frames(self.draw_pane_frames);
}
Expand Down
Loading

0 comments on commit 1e13076

Please sign in to comment.