From aea52d0891cb44b687f9c25b139f83f808001c32 Mon Sep 17 00:00:00 2001 From: Adrian Papari Date: Mon, 26 Jan 2026 23:23:12 +0100 Subject: [PATCH 1/6] feat(webgl2): add `responsive_resize` option for CSS-controlled layouts --- src/backend/webgl2.rs | 51 +++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/backend/webgl2.rs b/src/backend/webgl2.rs index 11dec5b..b3cd13d 100644 --- a/src/backend/webgl2.rs +++ b/src/backend/webgl2.rs @@ -77,6 +77,8 @@ pub struct WebGl2BackendOptions { measure_performance: bool, /// Enable console debugging and introspection API. console_debug_api: bool, + /// Use responsive resize mode (CSS controls canvas display size). + responsive_resize: bool, } impl WebGl2BackendOptions { @@ -219,6 +221,19 @@ impl WebGl2BackendOptions { self.console_debug_api = true; self } + + /// Enables responsive resize mode for CSS-controlled layouts. + /// + /// When enabled, the backend clears inline CSS dimensions after resize operations, + /// allowing external CSS rules (e.g., `width: 100%`) to control the canvas display + /// size. The canvas buffer is still sized correctly for crisp HiDPI rendering. + /// + /// Use this when the canvas should automatically fill its container based on + /// CSS layout rules rather than having a fixed pixel size. + pub fn responsive_resize(mut self) -> Self { + self.responsive_resize = true; + self + } } /// WebGl2 backend for high-performance terminal rendering. @@ -389,12 +404,16 @@ impl WebGl2Backend { self } - /// Sets the canvas viewport and projection, reconfigures the terminal grid. + /// Resizes the terminal to match the current CSS display size of the canvas. + /// + /// This method reads the canvas's CSS dimensions and updates beamterm's + /// internal state, viewport, and grid layout accordingly. pub fn resize_canvas(&mut self) -> Result<(), Error> { - let size_px = self.beamterm.canvas_size(); + let width = self.beamterm.canvas().client_width(); + let height = self.beamterm.canvas().client_height(); // resize the terminal grid and viewport - self.beamterm.resize(size_px.0, size_px.1)?; + self.beamterm.resize(width, height)?; // clear any hyperlink cells; we'll get them in the next draw call if let Some(hyperlink_cells) = &mut self.hyperlink_cells { @@ -417,17 +436,14 @@ impl WebGl2Backend { /// Checks if the canvas size matches the display size and resizes it if necessary. fn check_canvas_resize(&mut self) -> Result<(), Error> { - let canvas = self.beamterm.canvas(); - let display_width = canvas.client_width() as u32; - let display_height = canvas.client_height() as u32; - - let buffer_width = canvas.width(); - let buffer_height = canvas.height(); - - if display_width != buffer_width || display_height != buffer_height { - canvas.set_width(display_width); - canvas.set_height(display_height); - + // Compare CSS display size against beamterm's stored logical size. + // Both are in CSS/logical pixels, so DPR scaling is handled correctly + // by beamterm internally (buffer = logical × DPR). + let display_width = self.beamterm.canvas().client_width(); + let display_height = self.beamterm.canvas().client_height(); + let (stored_width, stored_height) = self.beamterm.canvas_size(); + + if display_width != stored_width || display_height != stored_height { self.resize_canvas()?; } @@ -707,6 +723,13 @@ impl Backend for WebGl2Backend { self.beamterm.render_frame().map_err(Error::from)?; self.toggle_cursor(); // restore cell to previous state + // For responsive layouts, clear inline CSS so external rules take effect + if self.options.responsive_resize { + let style = self.beamterm.canvas().style(); + let _ = style.remove_property("width"); + let _ = style.remove_property("height"); + } + self.measure_end(WEBGL_RENDER_MARK); Ok(()) From 9b833fcdf9e96f624d56036fc55c90e9f062f02e Mon Sep 17 00:00:00 2001 From: Adrian Papari Date: Tue, 27 Jan 2026 20:09:37 +0100 Subject: [PATCH 2/6] add WebGl2BackendOptions::disable_auto_css_resize --- src/backend/webgl2.rs | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/backend/webgl2.rs b/src/backend/webgl2.rs index b3cd13d..63b7308 100644 --- a/src/backend/webgl2.rs +++ b/src/backend/webgl2.rs @@ -77,8 +77,8 @@ pub struct WebGl2BackendOptions { measure_performance: bool, /// Enable console debugging and introspection API. console_debug_api: bool, - /// Use responsive resize mode (CSS controls canvas display size). - responsive_resize: bool, + /// Disable automatic canvas CSS sizing (let external CSS control dimensions). + disable_auto_css_resize: bool, } impl WebGl2BackendOptions { @@ -222,16 +222,17 @@ impl WebGl2BackendOptions { self } - /// Enables responsive resize mode for CSS-controlled layouts. + /// Disables automatic canvas CSS sizing for CSS-controlled layouts. /// - /// When enabled, the backend clears inline CSS dimensions after resize operations, - /// allowing external CSS rules (e.g., `width: 100%`) to control the canvas display - /// size. The canvas buffer is still sized correctly for crisp HiDPI rendering. + /// When called, the renderer does not set inline CSS `width` and `height` + /// properties on the canvas, allowing external CSS rules (flexbox, grid, + /// percentages) to control the canvas display size. The canvas buffer is + /// still sized correctly for crisp HiDPI rendering. /// - /// Use this when the canvas should automatically fill its container based on - /// CSS layout rules rather than having a fixed pixel size. - pub fn responsive_resize(mut self) -> Self { - self.responsive_resize = true; + /// Use this when the canvas should fill its container based on CSS layout + /// rules rather than having a fixed pixel size. + pub fn disable_auto_css_resize(mut self) -> Self { + self.disable_auto_css_resize = true; self } } @@ -688,6 +689,8 @@ impl WebGl2Backend { beamterm }; + let beamterm = beamterm.auto_resize_canvas_css(!options.disable_auto_css_resize); + Ok(beamterm.build()?) } } @@ -723,13 +726,6 @@ impl Backend for WebGl2Backend { self.beamterm.render_frame().map_err(Error::from)?; self.toggle_cursor(); // restore cell to previous state - // For responsive layouts, clear inline CSS so external rules take effect - if self.options.responsive_resize { - let style = self.beamterm.canvas().style(); - let _ = style.remove_property("width"); - let _ = style.remove_property("height"); - } - self.measure_end(WEBGL_RENDER_MARK); Ok(()) From e36c913a1ebbdbcb7f5773bab7da9232a80d46d6 Mon Sep 17 00:00:00 2001 From: Adrian Papari Date: Tue, 27 Jan 2026 20:31:41 +0100 Subject: [PATCH 3/6] bump beamterm to 0.14.0 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58f11a2..5044b71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,9 +33,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "beamterm-data" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5a70ff46e4e31f7b921e7c1c527cb4086765eb2393dff52a1a67a7c71e199c0" +checksum = "c27be7035a920d4507f78264a0ee99fcd70e7d179be4b453da737f5e40155e04" dependencies = [ "compact_str", "miniz_oxide", @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "beamterm-renderer" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89eb957a01ba980c6cc8718ffc4186630e0e04306805be2e6dadec7294d795fb" +checksum = "9b67db3888a56bc541c93e58196abcf4385446545d4889601f09ab0569093706" dependencies = [ "beamterm-data", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 6da5791..fadcae4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ ratatui = { version = "0.30", default-features = false, features = ["all-widgets console_error_panic_hook = "0.1.7" thiserror = "2.0.18" bitvec = { version = "1.0.1", default-features = false, features = ["alloc", "std"] } -beamterm-renderer = "0.13.0" +beamterm-renderer = "0.14.0" unicode-width = "0.2.2" [dev-dependencies] From 14326f71cdec6b1d23cd02bfe1aea6fd0a7ebcf0 Mon Sep 17 00:00:00 2001 From: Adrian Papari Date: Wed, 28 Jan 2026 08:24:08 +0100 Subject: [PATCH 4/6] actually use disable_auto_css_resize somewhere --- examples/demo/index.html | 9 +++++++++ examples/demo/src/main.rs | 6 +----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/demo/index.html b/examples/demo/index.html index 1d67f95..6b800cd 100644 --- a/examples/demo/index.html +++ b/examples/demo/index.html @@ -5,7 +5,11 @@ Ratzilla Demo