diff --git a/CHANGELOG.md b/CHANGELOG.md index 4296da09..5c40b8cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,11 @@ `key-bindings.color-theme-toggle` key bindings. These can be used to switch between the primary and alternative color themes. They are not bound by default. +* Support for private mode 2031 - [_Dark and Light Mode + Detection_](https://contour-terminal.org/vt-extensions/color-palette-update-notifications/) + ([#2025][2025]) + +[2025]: https://codeberg.org/dnkl/foot/issues/2025 ### Changed diff --git a/csi.c b/csi.c index b66fda21..e8b2c492 100644 --- a/csi.c +++ b/csi.c @@ -563,6 +563,10 @@ decset_decrst(struct terminal *term, unsigned param, bool enable) #endif break; + case 2031: + term->report_theme_changes = enable; + break; + case 2048: if (enable) term_enable_size_notifications(term); @@ -657,6 +661,7 @@ decrqm(const struct terminal *term, unsigned param) case 2027: return term->conf->tweak.grapheme_width_method != GRAPHEME_WIDTH_DOUBLE ? DECRPM_PERMANENTLY_RESET : decrpm(term->grapheme_shaping); + case 2031: return decrpm(term->report_theme_changes); case 2048: return decrpm(term->size_notifications); case 8452: return decrpm(term->sixel.cursor_right_of_graphics); case 737769: return decrpm(term_ime_is_enabled(term)); @@ -702,6 +707,7 @@ xtsave(struct terminal *term, unsigned param) case 2004: term->xtsave.bracketed_paste = term->bracketed_paste; break; case 2026: term->xtsave.app_sync_updates = term->render.app_sync_updates.enabled; break; case 2027: term->xtsave.grapheme_shaping = term->grapheme_shaping; break; + case 2031: term->xtsave.report_theme_changes = term->report_theme_changes; break; case 2048: term->xtsave.size_notifications = term->size_notifications; break; case 8452: term->xtsave.sixel_cursor_right_of_graphics = term->sixel.cursor_right_of_graphics; break; case 737769: term->xtsave.ime = term_ime_is_enabled(term); break; @@ -746,6 +752,7 @@ xtrestore(struct terminal *term, unsigned param) case 2004: enable = term->xtsave.bracketed_paste; break; case 2026: enable = term->xtsave.app_sync_updates; break; case 2027: enable = term->xtsave.grapheme_shaping; break; + case 2031: enable = term->xtsave.report_theme_changes; break; case 2048: enable = term->xtsave.size_notifications; break; case 8452: enable = term->xtsave.sixel_cursor_right_of_graphics; break; case 737769: enable = term->xtsave.ime; break; @@ -1539,6 +1546,32 @@ csi_dispatch(struct terminal *term, uint8_t final) break; } + case 'n': { + const int param = vt_param_get(term, 0, 0); + + switch (param) { + case 996: { /* Query current theme mode (see private mode 2031) */ + /* + * 1 - dark mode + * 2 - light mode + * + * In foot, the themes aren't necessarily light/dark, + * but by convention, the primary theme is dark, and + * the alternative theme is light. + */ + char reply[16] = {0}; + int chars = snprintf( + reply, sizeof(reply), + "\033[?997;%dn", + term->colors.active_theme == COLOR_THEME1 ? 1 : 2); + + term_to_slave(term, reply, chars); + break; + } + } + break; + } + case 'p': { /* * Request status of ECMA-48/"ANSI" private mode (DECRQM diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index 6c702738..40906ebf 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -337,6 +337,9 @@ that corresponds to one of the following modes: | 2027 : contour : Grapheme cluster processing +| 2031 +: contour +: Request color theme updates | 2048 : TODO : In-band window resize notifications @@ -657,6 +660,13 @@ manipulation sequences. The generic format is: : xterm : Report the current entry on the palette stack, and the number of palettes stored on the stack. +| \\E[ ? 996 n +: Query the current (color) theme mode +: contour +: The current color theme mode (light or dark) is reported as *CSI ? + 997 ; 1|2 n*, where *1* means dark and *2* light. By convention, the + primary theme in foot is considered dark, and the alternative theme + light. # OSC diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index af6f7875..85a7cf7b 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -958,6 +958,10 @@ The colors are in RRGGBB format (i.e. plain old 6-digit hex values, without prefix). That is, they do *not* have an alpha component. You can configure the background transparency with the _alpha_ option. +In the context of private mode 2031 (Dark and Light Mode detection), +the primary theme (i.e. the *colors* section) is considered to be the +dark theme (since the default theme is dark). + *cursor* Two space separated RRGGBB values (i.e. plain old 6-digit hex values, without prefix) specifying the foreground (text) and @@ -1093,6 +1097,10 @@ Note that values are not inherited. That is, if you set a value in *colors*, but not in *colors2*, the value from *colors* is not inherited by *colors2*. +In the context of private mode 2031 (Dark and Light Mode detection), +the primary theme (i.e. the *colors2* section) is considered to be the +light theme (since the default theme is dark). + # SECTION: csd This section controls the look of the _CSDs_ (Client Side diff --git a/input.c b/input.c index ebb646c6..b6c56fde 100644 --- a/input.c +++ b/input.c @@ -492,6 +492,9 @@ execute_binding(struct seat *seat, struct terminal *term, wayl_win_alpha_changed(term->window); term_font_subpixel_changed(term); + if (term->report_theme_changes) + term_to_slave(term, "\033[?997;1n", 9); + term_damage_view(term); term_damage_margins(term); render_refresh(term); @@ -506,6 +509,9 @@ execute_binding(struct seat *seat, struct terminal *term, wayl_win_alpha_changed(term->window); term_font_subpixel_changed(term); + if (term->report_theme_changes) + term_to_slave(term, "\033[?997;2n", 9); + term_damage_view(term); term_damage_margins(term); render_refresh(term); @@ -516,9 +522,15 @@ execute_binding(struct seat *seat, struct terminal *term, if (term->colors.active_theme == COLOR_THEME1) { term_theme_apply(term, &term->conf->colors2); term->colors.active_theme = COLOR_THEME2; + + if (term->report_theme_changes) + term_to_slave(term, "\033[?997;2n", 9); } else { term_theme_apply(term, &term->conf->colors); term->colors.active_theme = COLOR_THEME1; + + if (term->report_theme_changes) + term_to_slave(term, "\033[?997;1n", 9); } wayl_win_alpha_changed(term->window); diff --git a/terminal.h b/terminal.h index 45e13925..e6499ef7 100644 --- a/terminal.h +++ b/terminal.h @@ -518,6 +518,7 @@ struct terminal { bool num_lock_modifier; bool bell_action_enabled; + bool report_theme_changes; /* Saved DECSET modes - we save the SET state */ struct { @@ -548,6 +549,7 @@ struct terminal { bool ime:1; bool app_sync_updates:1; bool grapheme_shaping:1; + bool report_theme_changes:1; bool size_notifications:1;