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:
Justin M. Keyes
2019-02-17 11:32:18 +01:00
parent 6bd6927656
commit d3dc946155
4 changed files with 49 additions and 8 deletions

View File

@@ -83,10 +83,10 @@ EXTERN struct nvim_stats_s {
int64_t redraw;
} g_stats INIT(= { 0, 0 });
/* Values for "starting" */
#define NO_SCREEN 2 /* no screen updating yet */
#define NO_BUFFERS 1 /* not all buffers loaded yet */
/* 0 not starting anymore */
// Values for "starting".
#define NO_SCREEN 2 // no screen updating yet
#define NO_BUFFERS 1 // not all buffers loaded yet
// 0 not starting anymore
/*
* Number of Rows and Columns in the screen.

View File

@@ -883,7 +883,7 @@ set_options_default (
/// @param name The name of the option
/// @param val The value of the option
/// @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
{
int opt_idx = findoption(name);

View File

@@ -357,12 +357,28 @@ static bool handle_forced_escape(TermInput *input)
static void set_bg_deferred(void **argv)
{
char *bgvalue = argv[0];
set_string_default("bg", bgvalue, false);
if (!option_was_set("bg")) {
set_option_value("bg", 0, bgvalue, 0);
if (starting) {
// Wait until after startup, so OptionSet is triggered.
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)
{
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 luminance = (0.299 * r) + (0.587 * g) + (0.114 * b); // CCIR 601
char *bgvalue = luminance < 0.5 ? "dark" : "light";
DLOG("bg response: %s", bgvalue);
loop_schedule(&main_loop, event_create(set_bg_deferred, 1, bgvalue));
} else {
DLOG("failed to parse bg response");
}
return true;
}

View File

@@ -836,6 +836,28 @@ describe('TUI background color', function()
..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]')
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)
it('handles '..color..' as '..bg, function()
feed_data('\027]11;rgb:'..color..'\007:echo &background\n')