From 0f4cca9c5516375c2a9a6a17ca6b91308ef382f2 Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 25 Feb 2023 16:17:29 -0500 Subject: [PATCH] check outstanding kernel patch into doc/ so it's not forgotten --- doc/0001-console-answer-OSC-10-and-11.patch | 207 ++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 doc/0001-console-answer-OSC-10-and-11.patch diff --git a/doc/0001-console-answer-OSC-10-and-11.patch b/doc/0001-console-answer-OSC-10-and-11.patch new file mode 100644 index 000000000..bf4d877c4 --- /dev/null +++ b/doc/0001-console-answer-OSC-10-and-11.patch @@ -0,0 +1,207 @@ +From 1af86bbfa0a2d7e50d9535834b3bfc241bf334d8 Mon Sep 17 00:00:00 2001 +From: nick black +Date: Mon, 24 Jan 2022 00:33:21 -0500 +Subject: [PATCH] console: answer OSC 10 and 11 + +XTerm and many other terminal emulators implement +Operating System Commands 10 and 11, allowing the +default foreground/background to be set and queried. +Extend the VT control sequence parser to recognize +and support these queries. + +The VT already implements two OSCs, for changing +and resetting the palette. In doing so (many years +ago), it broke from the ANSI standard, and did not +require an ST terminator. Read all about it in +xterm(1) (see "brokenLinuxOSC"). I have followed this +grand tradition, and similarly not required ST. +Note that ST can still be safely sent by a client +program, as the VT consumes it. Indeed, my Notcurses +library does exactly this. + +"Don't VTs always have black backgrounds?" Nope, you +can change the default background color with any +number of ANSI sequences, and then use the VT's +Private CSI "ESC [ 8 ]" to make the current color pair +the default attributes. Try it at home with, say: + + printf %b '\e[46m' '\e[8]' '\e[H\e[J' + +The response follows XTerm's effective lead, using +%02x/%02x/%02x to format the RGB value, rather than +the %02x%02x%02x preferred by the preexisting +P (set palette) OSC. This was done to simplify +client libraries. Note that the spirit of the law, +that the reply is a "control sequence of the same +form which can be used to set", cannot be easily +honored given the semantics of the Linux private CSI +sequence. So it goes. + +As a result, notcurses-info now properly detects the +default colors dynamically. Where it used to say: + + no known default fg no known default bg + +It now says on boot: + + notcurses 3.0.4 on Linux 5.16.0nlb VT + ... + default fg 0xaaaaaa default bg 0x000000 + +and after a change like that above: + + notcurses 3.0.4 on Linux 5.16.0nlb VT + ... + default fg 0xaaaaaa default bg 0xaa5500 + +This is necessary to produce readable multicolor text +while respecting the user's background choice. + +Signed-off-by: nick black +--- + drivers/tty/vt/vt.c | 67 ++++++++++++++++++++++++++++------ + include/linux/console_struct.h | 1 + + 2 files changed, 58 insertions(+), 11 deletions(-) + +diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c +index f8c87c4d7399..a10629bcaaa1 100644 +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -1878,6 +1878,31 @@ int mouse_reporting(void) + return vc_cons[fg_console].d->vc_report_mouse; + } + ++/* handle the OSC query specified by vc->vc_oscmd. we currently handle only 10 ++ * and 11 (default foreground and default background, respectively). ++ */ ++static void handle_osc_query(struct tty_struct *tty, const struct vc_data *vc) ++{ ++ char buf[20]; ++ int len, idx; ++ /* response payload conforms to XTerm: %02x/%02x/%02x for R, G, and B. */ ++ switch (vc->vc_oscmd) { ++ case 10: /* get default foreground */ ++ idx = vc->vc_def_color & 0x0f; ++ break; ++ case 11: /* get default background */ ++ idx = (vc->vc_def_color & 0xf0) >> 4; ++ break; ++ default: ++ return; ++ } ++ /* transpose internal BGR to RGB on output */ ++ len = snprintf(buf, sizeof(buf), "\x1b]%d;rgb:%02x/%02x/%02x\x1b\\", ++ vc->vc_oscmd, vc->vc_palette[idx * 3 + 2], ++ vc->vc_palette[idx * 3 + 1], vc->vc_palette[idx * 3]); ++ respond_string(buf, len, tty->port); ++} ++ + /* console_lock is held */ + static void set_mode(struct vc_data *vc, int on_off) + { +@@ -2075,8 +2100,8 @@ static void restore_cur(struct vc_data *vc) + } + + enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, +- EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd, +- ESpalette, ESosc, ESapc, ESpm, ESdcs }; ++ EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ++ ESpalette, ESosc, ESoscmd, ESoscparam, ESapc, ESpm, ESdcs }; + + /* console_lock is held (except via vc_init()) */ + static void reset_terminal(struct vc_data *vc, int do_clear) +@@ -2230,7 +2255,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) + vc->vc_state = ESsquare; + return; + case ']': +- vc->vc_state = ESnonstd; ++ vc->vc_state = ESosc; + return; + case '_': + vc->vc_state = ESapc; +@@ -2287,7 +2312,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) + return; + } + return; +- case ESnonstd: ++ case ESosc: ++ /* Operating System Commands are traditionally terminated with an ST ++ * or a BEL, but Linux historically eschews said terminators. ++ */ + if (c=='P') { /* palette escape sequence */ + for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++) + vc->vc_par[vc->vc_npar] = 0; +@@ -2297,9 +2325,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) + } else if (c=='R') { /* reset palette */ + reset_palette(vc); + vc->vc_state = ESnormal; +- } else if (c>='0' && c<='9') +- vc->vc_state = ESosc; +- else ++ } else if (isdigit(c)) { ++ vc->vc_oscmd = c - '0'; ++ vc->vc_state = ESoscmd; ++ } else + vc->vc_state = ESnormal; + return; + case ESpalette: +@@ -2348,7 +2377,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) + if (c == ';' && vc->vc_npar < NPAR - 1) { + vc->vc_npar++; + return; +- } else if (c>='0' && c<='9') { ++ } else if (isdigit(c)) { + vc->vc_par[vc->vc_npar] *= 10; + vc->vc_par[vc->vc_npar] += c - '0'; + return; +@@ -2556,7 +2585,23 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) + return; + case ESapc: + return; +- case ESosc: ++ case ESoscmd: /* extract the first OSC param, the command */ ++ if (isdigit(c)) { ++ vc->vc_oscmd *= 10; ++ vc->vc_oscmd += c - '0'; ++ } else if (c == ';') { ++ vc->vc_state = ESoscparam; ++ } else { ++ vc->vc_state = ESnormal; ++ } ++ return; ++ case ESoscparam: /* extract second OSC param */ ++ /* All recognized numeric OSC commands take only '?', indicating a query. ++ * See note above regarding ESosc about lack of OSC terminator ST. ++ */ ++ if (c == '?') ++ handle_osc_query(tty, vc); ++ vc->vc_state = ESnormal; + return; + case ESpm: + return; +@@ -3441,8 +3486,8 @@ static void con_cleanup(struct tty_struct *tty) + } + + static int default_color = 7; /* white */ +-static int default_italic_color = 2; // green (ASCII) +-static int default_underline_color = 3; // cyan (ASCII) ++static int default_italic_color = 2; /* green */ ++static int default_underline_color = 3; /* cyan */ + module_param_named(color, default_color, int, S_IRUGO | S_IWUSR); + module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR); + module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR); +diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h +index d5b9c8d40c18..6d4fa51b62de 100644 +--- a/include/linux/console_struct.h ++++ b/include/linux/console_struct.h +@@ -128,6 +128,7 @@ struct vc_data { + /* VT terminal data */ + unsigned int vc_state; /* Escape sequence parser state */ + unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */ ++ unsigned int vc_oscmd; /* Operating System Command selector */ + /* data for manual vt switching */ + struct vt_mode vt_mode; + struct pid *vt_pid; +-- +2.34.1 +