diff options
-rw-r--r-- | runtime/doc/options.txt | 19 | ||||
-rw-r--r-- | src/nvim/main.c | 2 | ||||
-rw-r--r-- | src/nvim/option.c | 5 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 7 | ||||
-rw-r--r-- | src/nvim/options.lua | 7 | ||||
-rw-r--r-- | src/nvim/syntax.c | 4 | ||||
-rw-r--r-- | src/nvim/ui.c | 12 | ||||
-rw-r--r-- | src/nvim/ui_compositor.c | 48 | ||||
-rw-r--r-- | test/functional/ui/cursor_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 115 |
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}) |