mirror of
https://github.com/neovim/neovim.git
synced 2024-12-22 04:05:09 -07:00
Automatically detect terminal background and set bg=dark or bg=light
xterm-compatible terminals support reporting their configured colors back to the application. Use this to obtain the current background color, compute its luminance to classify it as light or dark, and set 'bg' accordingly. Also set the default for 'bg', so that `:set bg&` will revert to that detected default.
This commit is contained in:
parent
ef72303a1f
commit
298608f88c
@ -874,7 +874,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.
|
||||||
static void set_string_default(const char *name, char *val, bool allocated)
|
void set_string_default(const char *name, char *val, bool allocated)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int opt_idx = findoption((char_u *)name);
|
int opt_idx = findoption((char_u *)name);
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
#include "nvim/api/vim.h"
|
#include "nvim/api/vim.h"
|
||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
|
#include "nvim/charset.h"
|
||||||
#include "nvim/main.h"
|
#include "nvim/main.h"
|
||||||
#include "nvim/misc2.h"
|
#include "nvim/misc2.h"
|
||||||
|
#include "nvim/option.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/event/rstream.h"
|
#include "nvim/event/rstream.h"
|
||||||
@ -320,6 +322,66 @@ static bool handle_forced_escape(TermInput *input)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_bg_deferred(void **argv)
|
||||||
|
{
|
||||||
|
char *bgvalue = argv[0];
|
||||||
|
set_string_default("bg", bgvalue, false);
|
||||||
|
if (!option_was_set((char_u *)"bg")) {
|
||||||
|
set_option_value((char_u *)"bg", 0, (char_u *)bgvalue, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool handle_background_color(TermInput *input)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
size_t component = 0;
|
||||||
|
uint16_t rgb[] = { 0, 0, 0 };
|
||||||
|
uint16_t rgb_max[] = { 0, 0, 0 };
|
||||||
|
bool eat_backslash = false;
|
||||||
|
bool done = false;
|
||||||
|
bool bad = false;
|
||||||
|
if (rbuffer_size(input->read_stream.buffer) >= 9
|
||||||
|
&& !rbuffer_cmp(input->read_stream.buffer, "\x1b]11;rgb:", 9)) {
|
||||||
|
rbuffer_consumed(input->read_stream.buffer, 9);
|
||||||
|
RBUFFER_EACH(input->read_stream.buffer, c, i) {
|
||||||
|
count = i + 1;
|
||||||
|
if (eat_backslash) {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
} else if (c == '\x07') {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
} else if (c == '\x1b') {
|
||||||
|
eat_backslash = true;
|
||||||
|
} else if (bad) {
|
||||||
|
// ignore
|
||||||
|
} else if (c == '/') {
|
||||||
|
if (component < 3) {
|
||||||
|
component++;
|
||||||
|
}
|
||||||
|
} else if (ascii_isxdigit(c)) {
|
||||||
|
if (component < 3 && rgb_max[component] != 0xffff) {
|
||||||
|
rgb_max[component] = (uint16_t)((rgb_max[component] << 4) | 0xf);
|
||||||
|
rgb[component] = (uint16_t)((rgb[component] << 4) | hex2nr(c));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bad = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rbuffer_consumed(input->read_stream.buffer, count);
|
||||||
|
if (done && !bad && rgb_max[0] && rgb_max[1] && rgb_max[2]) {
|
||||||
|
double r = (double)rgb[0] / (double)rgb_max[0];
|
||||||
|
double g = (double)rgb[1] / (double)rgb_max[1];
|
||||||
|
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";
|
||||||
|
loop_schedule(&main_loop, event_create(1, set_bg_deferred, 1, bgvalue));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void restart_reading(void **argv);
|
static void restart_reading(void **argv);
|
||||||
|
|
||||||
static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
|
static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
|
||||||
@ -351,7 +413,8 @@ static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
|
|||||||
do {
|
do {
|
||||||
if (handle_focus_event(input)
|
if (handle_focus_event(input)
|
||||||
|| handle_bracketed_paste(input)
|
|| handle_bracketed_paste(input)
|
||||||
|| handle_forced_escape(input)) {
|
|| handle_forced_escape(input)
|
||||||
|
|| handle_background_color(input)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ typedef struct {
|
|||||||
int enter_insert_mode, enter_replace_mode, exit_insert_mode;
|
int enter_insert_mode, enter_replace_mode, exit_insert_mode;
|
||||||
int set_rgb_foreground, set_rgb_background;
|
int set_rgb_foreground, set_rgb_background;
|
||||||
int enable_focus_reporting, disable_focus_reporting;
|
int enable_focus_reporting, disable_focus_reporting;
|
||||||
|
int get_bg;
|
||||||
} unibi_ext;
|
} unibi_ext;
|
||||||
} TUIData;
|
} TUIData;
|
||||||
|
|
||||||
@ -125,6 +126,7 @@ static void terminfo_start(UI *ui)
|
|||||||
data->unibi_ext.exit_insert_mode = -1;
|
data->unibi_ext.exit_insert_mode = -1;
|
||||||
data->unibi_ext.enable_focus_reporting = -1;
|
data->unibi_ext.enable_focus_reporting = -1;
|
||||||
data->unibi_ext.disable_focus_reporting = -1;
|
data->unibi_ext.disable_focus_reporting = -1;
|
||||||
|
data->unibi_ext.get_bg = -1;
|
||||||
data->out_fd = 1;
|
data->out_fd = 1;
|
||||||
data->out_isatty = os_isatty(data->out_fd);
|
data->out_isatty = os_isatty(data->out_fd);
|
||||||
// setup unibilium
|
// setup unibilium
|
||||||
@ -140,6 +142,8 @@ static void terminfo_start(UI *ui)
|
|||||||
// Enter alternate screen and clear
|
// Enter alternate screen and clear
|
||||||
unibi_out(ui, unibi_enter_ca_mode);
|
unibi_out(ui, unibi_enter_ca_mode);
|
||||||
unibi_out(ui, unibi_clear_screen);
|
unibi_out(ui, unibi_clear_screen);
|
||||||
|
// Ask the terminal to send us the background color
|
||||||
|
unibi_out(ui, data->unibi_ext.get_bg);
|
||||||
// Enable bracketed paste
|
// Enable bracketed paste
|
||||||
unibi_out(ui, data->unibi_ext.enable_bracketed_paste);
|
unibi_out(ui, data->unibi_ext.enable_bracketed_paste);
|
||||||
// Enable focus reporting
|
// Enable focus reporting
|
||||||
@ -829,6 +833,8 @@ static void fix_terminfo(TUIData *data)
|
|||||||
data->unibi_ext.disable_focus_reporting = (int)unibi_add_ext_str(ut, NULL,
|
data->unibi_ext.disable_focus_reporting = (int)unibi_add_ext_str(ut, NULL,
|
||||||
"\x1b[?1004l");
|
"\x1b[?1004l");
|
||||||
|
|
||||||
|
data->unibi_ext.get_bg = (int)unibi_add_ext_str(ut, NULL, "\x1b]11;?\x07");
|
||||||
|
|
||||||
#define XTERM_SETAF \
|
#define XTERM_SETAF \
|
||||||
"\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"
|
"\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"
|
||||||
#define XTERM_SETAB \
|
#define XTERM_SETAB \
|
||||||
|
Loading…
Reference in New Issue
Block a user