[PATCH 18/20] fbconsole: implement alternate screen buffer (ESC[?1049h/l)
Ahmad Fatoum
a.fatoum at barebox.org
Sun May 3 01:33:20 PDT 2026
The alternate screen buffer is distinct from the scrollback-enabled
primary buffer and meant for full screen applications.
The ?1049 mode in particular is a superset of it that includes saving
the cursor and clearing the buffer when entering.
Implement it via taking a snapshot of the framebuffer's pixels.
Link: https://terminalguide.namepad.de/mode/p1049/
Signed-off-by: Ahmad Fatoum <a.fatoum at barebox.org>
---
drivers/video/fbconsole.c | 46 +++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c
index bed55de7571e..3a2a680fc719 100644
--- a/drivers/video/fbconsole.c
+++ b/drivers/video/fbconsole.c
@@ -81,6 +81,10 @@ struct fbc_priv {
struct fbc_screen_state cur;
struct fbc_screen_state saved; /* DEC cursor save (\e7) */
+ struct fbc_screen_state altscreen_saved;
+ void *altscreen_buf; /* pixel snapshot while in alternate screen */
+ size_t altscreen_size;
+
unsigned int rotation;
enum state_t state;
@@ -651,6 +655,21 @@ static bool fbc_parse_csi(struct fbc_priv *priv)
/* show cursor now */
toggle_cursor_visibility(priv);
return true;
+ case 1049: /* alternate screen: save pixel buffer and state */
+ if (!priv->altscreen_buf) {
+ void *src = gui_screen_render_buffer(priv->sc);
+ size_t sz = priv->fb->line_length * priv->fb->yres;
+
+ priv->altscreen_buf = memdup(src, sz);
+ if (priv->altscreen_buf) {
+ priv->altscreen_size = sz;
+ priv->altscreen_saved = priv->cur;
+ }
+ priv->cur = (struct fbc_screen_state){};
+ fbc_reset_colors(priv);
+ cls(priv);
+ }
+ return true;
}
break;
case 'l':
@@ -664,6 +683,27 @@ static bool fbc_parse_csi(struct fbc_priv *priv)
/* hide cursor now */
priv->cur.flags |= HIDE_CURSOR;
return true;
+ case 1049: /* alternate screen: restore pixel buffer and state */
+ if (priv->altscreen_buf) {
+ void *dst = gui_screen_render_buffer(priv->sc);
+ size_t sz = priv->fb->line_length * priv->fb->yres;
+
+ if (sz == priv->altscreen_size) {
+ memcpy(dst, priv->altscreen_buf, sz);
+ gu_screen_blit(priv->sc);
+ } else {
+ cls(priv);
+ }
+ free(priv->altscreen_buf);
+ priv->altscreen_buf = NULL;
+ priv->altscreen_size = 0;
+ priv->cur = priv->altscreen_saved;
+ } else {
+ priv->cur = (struct fbc_screen_state){};
+ fbc_reset_colors(priv);
+ cls(priv);
+ }
+ return true;
}
break;
case 'J':
@@ -914,6 +954,12 @@ static int fbc_close(struct console_device *cdev)
struct fbc_priv *priv = container_of(cdev,
struct fbc_priv, cdev);
+ if (priv->altscreen_buf) {
+ free(priv->altscreen_buf);
+ priv->altscreen_buf = NULL;
+ priv->altscreen_size = 0;
+ }
+
if (priv->active) {
fb_close(priv->sc);
priv->active = false;
--
2.47.3
More information about the barebox
mailing list