mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	Merge pull request #9575 from bfredl/redrawdebug
ui: implement better redrawdebug for the compositor
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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'
 | 
			
		||||
 
 | 
			
		||||
@@ -1847,6 +1847,13 @@ return {
 | 
			
		||||
      varname='p_ro',
 | 
			
		||||
      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'},
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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})
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user