aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/tui
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2016-07-12 22:52:10 -0700
committerJosh Triplett <josh@joshtriplett.org>2016-07-24 01:56:33 -0700
commit298608f88c463705cfd6ee47035c049dbb1d9fa0 (patch)
tree6c4fe7bafc57b400daf019a2dd24aa218815c66e /src/nvim/tui
parentef72303a1ff862fde6d9399941c091c0a0692cce (diff)
downloadrneovim-298608f88c463705cfd6ee47035c049dbb1d9fa0.tar.gz
rneovim-298608f88c463705cfd6ee47035c049dbb1d9fa0.tar.bz2
rneovim-298608f88c463705cfd6ee47035c049dbb1d9fa0.zip
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.
Diffstat (limited to 'src/nvim/tui')
-rw-r--r--src/nvim/tui/input.c65
-rw-r--r--src/nvim/tui/tui.c6
2 files changed, 70 insertions, 1 deletions
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index be256f3ebc..c41107d4d3 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -4,8 +4,10 @@
#include "nvim/api/vim.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
+#include "nvim/charset.h"
#include "nvim/main.h"
#include "nvim/misc2.h"
+#include "nvim/option.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
#include "nvim/event/rstream.h"
@@ -320,6 +322,66 @@ static bool handle_forced_escape(TermInput *input)
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 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 {
if (handle_focus_event(input)
|| handle_bracketed_paste(input)
- || handle_forced_escape(input)) {
+ || handle_forced_escape(input)
+ || handle_background_color(input)) {
continue;
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index d220df508a..c4efa69c4c 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -68,6 +68,7 @@ typedef struct {
int enter_insert_mode, enter_replace_mode, exit_insert_mode;
int set_rgb_foreground, set_rgb_background;
int enable_focus_reporting, disable_focus_reporting;
+ int get_bg;
} unibi_ext;
} TUIData;
@@ -125,6 +126,7 @@ static void terminfo_start(UI *ui)
data->unibi_ext.exit_insert_mode = -1;
data->unibi_ext.enable_focus_reporting = -1;
data->unibi_ext.disable_focus_reporting = -1;
+ data->unibi_ext.get_bg = -1;
data->out_fd = 1;
data->out_isatty = os_isatty(data->out_fd);
// setup unibilium
@@ -140,6 +142,8 @@ static void terminfo_start(UI *ui)
// Enter alternate screen and clear
unibi_out(ui, unibi_enter_ca_mode);
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
unibi_out(ui, data->unibi_ext.enable_bracketed_paste);
// 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,
"\x1b[?1004l");
+ data->unibi_ext.get_bg = (int)unibi_add_ext_str(ut, NULL, "\x1b]11;?\x07");
+
#define XTERM_SETAF \
"\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"
#define XTERM_SETAB \