aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/options.txt19
-rw-r--r--src/nvim/main.c2
-rw-r--r--src/nvim/option.c5
-rw-r--r--src/nvim/option_defs.h7
-rw-r--r--src/nvim/options.lua7
-rw-r--r--src/nvim/syntax.c4
-rw-r--r--src/nvim/ui.c12
-rw-r--r--src/nvim/ui_compositor.c48
-rw-r--r--test/functional/ui/cursor_spec.lua4
-rw-r--r--test/functional/ui/float_spec.lua115
10 files changed, 215 insertions, 8 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index a421f6b5e7..8fc8a04df3 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4552,6 +4552,25 @@ A jump table for the options with a short description can be found at |Q_op|.
set for the newly edited buffer.
See 'modifiable' for disallowing changes to the buffer.
+ *'redrawdebug'* *'rdb'*
+'redrawdebug' 'rdb' string (default '')
+ global
+ Flags to change the way redrawing works, for debugging purposes.
+ Most useful with 'writedelay' set to some reasonable value.
+ Supports the following flags:
+ compositor Indicate what redraws come from the compositor
+ by briefly flashing the redrawn regions in colors
+ indicating the redraw type. These are the highlight
+ groups used (and their default colors):
+ RedrawDebugNormal gui=reverse normal redraw passed through
+ RedrawDebugClear guibg=Yellow clear event passed through
+ RedrawDebugComposed guibg=Green redraw event modified by the
+ compositor (due to
+ overlapping grids, etc)
+ RedrawDebugRecompose guibg=Red redraw generated by the
+ compositor itself, due to a
+ grid being moved or deleted.
+
*'redrawtime'* *'rdt'*
'redrawtime' 'rdt' number (default 2000)
global
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 306d2f7bf5..b3654a0690 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -54,6 +54,7 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
#include "nvim/version.h"
#include "nvim/window.h"
#include "nvim/shada.h"
@@ -220,6 +221,7 @@ void early_init(void)
set_lang_var(); // set v:lang and v:ctype
init_signs();
+ ui_comp_syn_init();
}
#ifdef MAKE_LIB
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 9cdcf4cc34..d6dbb14653 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2191,6 +2191,7 @@ static void didset_options(void)
(void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true);
(void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true);
(void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, true);
+ (void)opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true);
(void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, false);
(void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
(void)opt_strings_flags(p_wop, p_wop_values, &wop_flags, true);
@@ -2650,6 +2651,10 @@ did_set_string_option(
if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true) != OK) {
errmsg = e_invarg;
}
+ } else if (varp == &p_rdb) { // 'redrawdebug'
+ if (opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true) != OK) {
+ errmsg = e_invarg;
+ }
} else if (varp == &p_sbo) { // 'scrollopt'
if (check_opt_strings(p_sbo, p_scbopt_values, true) != OK) {
errmsg = e_invarg;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 35fe3b5b00..a480de735d 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -511,6 +511,13 @@ EXTERN char_u *p_pm; // 'patchmode'
EXTERN char_u *p_path; // 'path'
EXTERN char_u *p_cdpath; // 'cdpath'
EXTERN long p_pyx; // 'pyxversion'
+EXTERN char_u *p_rdb; // 'redrawdebug'
+EXTERN unsigned rdb_flags;
+# ifdef IN_OPTION_C
+static char *(p_rdb_values[]) = { "compositor", NULL };
+# endif
+# define RDB_COMPOSITOR 0x001
+
EXTERN long p_rdt; // 'redrawtime'
EXTERN int p_remap; // 'remap'
EXTERN long p_re; // 'regexpengine'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 27f72f6441..c48366e205 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1848,6 +1848,13 @@ return {
defaults={if_true={vi=false}}
},
{
+ full_name='redrawdebug', abbreviation='rdb',
+ type='string', list='onecomma', scope={'global'},
+ vi_def=true,
+ varname='p_rdb',
+ defaults={if_true={vi=''}}
+ },
+ {
full_name='redrawtime', abbreviation='rdt',
type='number', scope={'global'},
vi_def=true,
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 354590b9ec..e39075739c 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -5970,6 +5970,10 @@ static const char *highlight_init_both[] = {
"default link Whitespace NonText",
"default link MsgSeparator StatusLine",
"default link NormalFloat Pmenu",
+ "RedrawDebugNormal cterm=reverse gui=reverse",
+ "RedrawDebugClear ctermbg=Yellow guibg=Yellow",
+ "RedrawDebugComposed ctermbg=Green guibg=Green",
+ "RedrawDebugRecompose ctermbg=Red guibg=Red",
NULL
};
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 7bd45507a6..fc4a3a403d 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -341,15 +341,15 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
flags, (const schar_T *)grid->chars + off,
(const sattr_T *)grid->attrs + off);
- if (p_wd) { // 'writedelay': flush & delay each time.
- int old_row = cursor_row, old_col = cursor_col;
- handle_T old_grid = cursor_grid_handle;
+ // 'writedelay': flush & delay each time.
+ if (p_wd && !(rdb_flags & RDB_COMPOSITOR)) {
// If 'writedelay' is active, set the cursor to indicate what was drawn.
- ui_grid_cursor_goto(grid->handle, row, MIN(clearcol, (int)Columns-1));
- ui_flush();
+ ui_call_grid_cursor_goto(grid->handle, row,
+ MIN(clearcol, (int)grid->Columns-1));
+ ui_call_flush();
uint64_t wd = (uint64_t)labs(p_wd);
os_microdelay(wd * 1000u, true);
- ui_grid_cursor_goto(old_grid, old_row, old_col);
+ pending_cursor_update = true; // restore the cursor later
}
}
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index 0f1abb5b7e..858ffbe5bc 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -49,6 +49,8 @@ static bool valid_screen = true;
static bool msg_scroll_mode = false;
static int msg_first_invalid = 0;
+static int dbghl_normal, dbghl_clear, dbghl_composed, dbghl_recompose;
+
void ui_comp_init(void)
{
if (compositor != NULL) {
@@ -81,6 +83,13 @@ void ui_comp_init(void)
ui_attach_impl(compositor);
}
+void ui_comp_syn_init(void)
+{
+ dbghl_normal = syn_check_group((char_u *)S_LEN("RedrawDebugNormal"));
+ dbghl_clear = syn_check_group((char_u *)S_LEN("RedrawDebugClear"));
+ dbghl_composed = syn_check_group((char_u *)S_LEN("RedrawDebugComposed"));
+ dbghl_recompose = syn_check_group((char_u *)S_LEN("RedrawDebugRecompose"));
+}
void ui_comp_attach(UI *ui)
{
@@ -385,9 +394,42 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
(const sattr_T *)attrbuf+skipstart);
}
+static void compose_debug(Integer startrow, Integer endrow, Integer startcol,
+ Integer endcol, int syn_id, bool delay)
+{
+ if (!(rdb_flags & RDB_COMPOSITOR)) {
+ return;
+ }
+
+ endrow = MIN(endrow, default_grid.Rows);
+ endcol = MIN(endcol, default_grid.Columns);
+ int attr = syn_id2attr(syn_id);
+
+ for (int row = (int)startrow; row < endrow; row++) {
+ ui_composed_call_raw_line(1, row, startcol, startcol, endcol, attr, false,
+ (const schar_T *)linebuf,
+ (const sattr_T *)attrbuf);
+ }
+
+
+ if (delay) {
+ debug_delay(endrow-startrow);
+ }
+}
+
+static void debug_delay(Integer lines)
+{
+ ui_call_flush();
+ uint64_t wd = (uint64_t)labs(p_wd);
+ uint64_t factor = (uint64_t)MAX(MIN(lines, 5), 1);
+ os_microdelay(factor * wd * 1000u, true);
+}
+
+
static void compose_area(Integer startrow, Integer endrow,
Integer startcol, Integer endcol)
{
+ compose_debug(startrow, endrow, startcol, endcol, dbghl_recompose, true);
endrow = MIN(endrow, default_grid.Rows);
endcol = MIN(endcol, default_grid.Columns);
if (endcol <= startcol) {
@@ -432,8 +474,11 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
if (flags & kLineFlagInvalid
|| kv_size(layers) > curgrid->comp_index+1
|| curgrid->blending) {
+ compose_debug(row, row+1, startcol, clearcol, dbghl_composed, true);
compose_line(row, startcol, clearcol, flags);
} else {
+ compose_debug(row, row+1, startcol, endcol, dbghl_normal, false);
+ compose_debug(row, row+1, endcol, clearcol, dbghl_clear, true);
ui_composed_call_raw_line(1, row, startcol, endcol, clearcol, clearattr,
flags, chunk, attrs);
}
@@ -493,6 +538,9 @@ static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top,
} else {
msg_first_invalid = MIN(msg_first_invalid, (int)top);
ui_composed_call_grid_scroll(1, top, bot, left, right, rows, cols);
+ if (rdb_flags & RDB_COMPOSITOR) {
+ debug_delay(2);
+ }
}
}
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index 4dc86f1e1f..6475eb2923 100644
--- a/test/functional/ui/cursor_spec.lua
+++ b/test/functional/ui/cursor_spec.lua
@@ -216,10 +216,10 @@ describe('ui/cursor', function()
if m.blinkwait then m.blinkwait = 700 end
end
if m.hl_id then
- m.hl_id = 50
+ m.hl_id = 54
m.attr = {background = Screen.colors.DarkGray}
end
- if m.id_lm then m.id_lm = 51 end
+ if m.id_lm then m.id_lm = 55 end
end
-- Assert the new expectation.
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index a88f69c49e..68a23db0a2 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -172,6 +172,121 @@ describe('floating windows', function()
end
end)
+ it('draws correctly with redrawdebug=compositor', function()
+ -- NB: we do not test that it produces the "correct" debug info
+ -- (as it is intermediate only, and is allowed to change by internal
+ -- refactors). Only check that it doesn't cause permanent glitches,
+ -- or something.
+ command("set redrawdebug=compositor")
+ command("set wd=1")
+ local buf = meths.create_buf(false,false)
+ local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ local expected_pos = {
+ [3]={{id=1001}, 'NW', 1, 2, 5, true},
+ }
+
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ |
+ ## grid 2
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ {1: }|
+ {2:~ }|
+ ]], float_pos=expected_pos}
+ else
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }{1: }{0: }|
+ {0:~ }{2:~ }{0: }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end
+
+
+ meths.win_set_config(win, {relative='editor', row=0, col=10})
+ expected_pos[3][4] = 0
+ expected_pos[3][5] = 10
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ |
+ ## grid 2
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ {1: }|
+ {2:~ }|
+ ]], float_pos=expected_pos}
+ else
+ screen:expect([[
+ ^ {1: } |
+ {0:~ }{2:~ }{0: }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end
+
+ meths.win_close(win, false)
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ |
+ ## grid 2
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ]])
+ else
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end
+ end)
+
it('return their configuration', function()
local buf = meths.create_buf(false, false)
local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=3, col=5})