mirror of
https://github.com/neovim/neovim.git
synced 2025-10-05 17:36:29 +00:00
TUI: rework background-color detection
- Like Vim, use set_option_value() followed by reset_option_was_set(). - Do not use set_string_default(), so the default is predictable. This affects `:set bg&`. - Wait until end-of-startup (VimEnter) to handle the response. The response is racey anyways, so timing is irrelevant. This allows OptionSet to be triggered, unlike during startup.
This commit is contained in:
@@ -83,10 +83,10 @@ EXTERN struct nvim_stats_s {
|
|||||||
int64_t redraw;
|
int64_t redraw;
|
||||||
} g_stats INIT(= { 0, 0 });
|
} g_stats INIT(= { 0, 0 });
|
||||||
|
|
||||||
/* Values for "starting" */
|
// Values for "starting".
|
||||||
#define NO_SCREEN 2 /* no screen updating yet */
|
#define NO_SCREEN 2 // no screen updating yet
|
||||||
#define NO_BUFFERS 1 /* not all buffers loaded yet */
|
#define NO_BUFFERS 1 // not all buffers loaded yet
|
||||||
/* 0 not starting anymore */
|
// 0 not starting anymore
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of Rows and Columns in the screen.
|
* Number of Rows and Columns in the screen.
|
||||||
|
@@ -883,7 +883,7 @@ set_options_default (
|
|||||||
/// @param name The name of the option
|
/// @param name The name of the option
|
||||||
/// @param val The value of the option
|
/// @param val The value of the option
|
||||||
/// @param allocated If true, do not copy default as it was already allocated.
|
/// @param allocated If true, do not copy default as it was already allocated.
|
||||||
void set_string_default(const char *name, char *val, bool allocated)
|
static void set_string_default(const char *name, char *val, bool allocated)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int opt_idx = findoption(name);
|
int opt_idx = findoption(name);
|
||||||
|
@@ -357,12 +357,28 @@ static bool handle_forced_escape(TermInput *input)
|
|||||||
static void set_bg_deferred(void **argv)
|
static void set_bg_deferred(void **argv)
|
||||||
{
|
{
|
||||||
char *bgvalue = argv[0];
|
char *bgvalue = argv[0];
|
||||||
set_string_default("bg", bgvalue, false);
|
if (starting) {
|
||||||
if (!option_was_set("bg")) {
|
// Wait until after startup, so OptionSet is triggered.
|
||||||
set_option_value("bg", 0, bgvalue, 0);
|
loop_schedule(&main_loop, event_create(set_bg_deferred, 1, bgvalue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!option_was_set("bg") && !strequal((char *)p_bg, bgvalue)) {
|
||||||
|
// Value differs, apply it.
|
||||||
|
set_option_value("bg", 0L, bgvalue, 0);
|
||||||
|
reset_option_was_set("bg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// During startup, tui.c requests the background color (see `ext.get_bg`).
|
||||||
|
//
|
||||||
|
// Here in input.c, we watch for the terminal response `\e]11;COLOR\a`. If
|
||||||
|
// COLOR matches `rgb:RRRR/GGGG/BBBB` where R, G, and B are hex digits, then
|
||||||
|
// compute the luminance[1] of the RGB color and classify it as light/dark
|
||||||
|
// accordingly. Note that the color components may have anywhere from one to
|
||||||
|
// four hex digits, and require scaling accordingly as values out of 4, 8, 12,
|
||||||
|
// or 16 bits.
|
||||||
|
//
|
||||||
|
// [1] https://en.wikipedia.org/wiki/Luma_%28video%29
|
||||||
static bool handle_background_color(TermInput *input)
|
static bool handle_background_color(TermInput *input)
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@@ -407,7 +423,10 @@ static bool handle_background_color(TermInput *input)
|
|||||||
double b = (double)rgb[2] / (double)rgb_max[2];
|
double b = (double)rgb[2] / (double)rgb_max[2];
|
||||||
double luminance = (0.299 * r) + (0.587 * g) + (0.114 * b); // CCIR 601
|
double luminance = (0.299 * r) + (0.587 * g) + (0.114 * b); // CCIR 601
|
||||||
char *bgvalue = luminance < 0.5 ? "dark" : "light";
|
char *bgvalue = luminance < 0.5 ? "dark" : "light";
|
||||||
|
DLOG("bg response: %s", bgvalue);
|
||||||
loop_schedule(&main_loop, event_create(set_bg_deferred, 1, bgvalue));
|
loop_schedule(&main_loop, event_create(set_bg_deferred, 1, bgvalue));
|
||||||
|
} else {
|
||||||
|
DLOG("failed to parse bg response");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -836,6 +836,28 @@ describe('TUI background color', function()
|
|||||||
..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]')
|
..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("triggers OptionSet event on terminal-response", function()
|
||||||
|
feed_data('\027:autocmd OptionSet background echo "did OptionSet, yay!"\n')
|
||||||
|
|
||||||
|
-- The child Nvim is running asynchronously; wait for it to register the
|
||||||
|
-- OptionSet handler.
|
||||||
|
feed_data('\027:autocmd OptionSet\n')
|
||||||
|
screen:expect({any='--- Autocommands ---'})
|
||||||
|
|
||||||
|
feed_data('\012') -- CTRL-L: clear the screen
|
||||||
|
screen:expect([[
|
||||||
|
{1: } |
|
||||||
|
{4:~ }|
|
||||||
|
{4:~ }|
|
||||||
|
{4:~ }|
|
||||||
|
{5:[No Name] 0,0-1 All}|
|
||||||
|
|
|
||||||
|
{3:-- TERMINAL --} |
|
||||||
|
]])
|
||||||
|
feed_data('\027]11;rgb:ffff/ffff/ffff\007')
|
||||||
|
screen:expect{any='did OptionSet, yay!'}
|
||||||
|
end)
|
||||||
|
|
||||||
local function assert_bg(color, bg)
|
local function assert_bg(color, bg)
|
||||||
it('handles '..color..' as '..bg, function()
|
it('handles '..color..' as '..bg, function()
|
||||||
feed_data('\027]11;rgb:'..color..'\007:echo &background\n')
|
feed_data('\027]11;rgb:'..color..'\007:echo &background\n')
|
||||||
|
Reference in New Issue
Block a user