mirror of
https://github.com/vim/vim.git
synced 2025-09-06 21:53:38 -04:00
patch 8.1.1517: when a popup changes all windows are redrawn
Problem: When a popup changes all windows are redrawn. Solution: Only update the lines that were affected. Add a file for profiling popup windows efficiency.
This commit is contained in:
parent
640d4f0c97
commit
4c063a0dab
1
Filelist
1
Filelist
@ -152,6 +152,7 @@ SRC_ALL = \
|
|||||||
src/testdir/if_ver*.vim \
|
src/testdir/if_ver*.vim \
|
||||||
src/testdir/color_ramp.vim \
|
src/testdir/color_ramp.vim \
|
||||||
src/testdir/silent.wav \
|
src/testdir/silent.wav \
|
||||||
|
src/testdir/popupbounce.vim \
|
||||||
src/proto.h \
|
src/proto.h \
|
||||||
src/protodef.h \
|
src/protodef.h \
|
||||||
src/proto/arabic.pro \
|
src/proto/arabic.pro \
|
||||||
|
@ -73,6 +73,7 @@ EXTERN short *TabPageIdxs INIT(= NULL);
|
|||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
// Array with size Rows x Columns containing zindex of popups.
|
// Array with size Rows x Columns containing zindex of popups.
|
||||||
EXTERN short *popup_mask INIT(= NULL);
|
EXTERN short *popup_mask INIT(= NULL);
|
||||||
|
EXTERN short *popup_mask_next INIT(= NULL);
|
||||||
|
|
||||||
// Flag set to TRUE when popup_mask needs to be updated.
|
// Flag set to TRUE when popup_mask needs to be updated.
|
||||||
EXTERN int popup_mask_refresh INIT(= TRUE);
|
EXTERN int popup_mask_refresh INIT(= TRUE);
|
||||||
|
@ -571,8 +571,7 @@ popup_adjust_position(win_T *wp)
|
|||||||
|| org_width != wp->w_width
|
|| org_width != wp->w_width
|
||||||
|| org_height != wp->w_height)
|
|| org_height != wp->w_height)
|
||||||
{
|
{
|
||||||
// TODO: redraw only windows that were below the popup.
|
redraw_all_later(VALID);
|
||||||
redraw_all_later(NOT_VALID);
|
|
||||||
popup_mask_refresh = TRUE;
|
popup_mask_refresh = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ int update_screen(int type_arg);
|
|||||||
int conceal_cursor_line(win_T *wp);
|
int conceal_cursor_line(win_T *wp);
|
||||||
void conceal_check_cursor_line(void);
|
void conceal_check_cursor_line(void);
|
||||||
void update_debug_sign(buf_T *buf, linenr_T lnum);
|
void update_debug_sign(buf_T *buf, linenr_T lnum);
|
||||||
int may_update_popup_mask(int type_arg);
|
|
||||||
void updateWindow(win_T *wp);
|
void updateWindow(win_T *wp);
|
||||||
int screen_get_current_line_off(void);
|
int screen_get_current_line_off(void);
|
||||||
void screen_line(int row, int coloff, int endcol, int clear_width, int flags);
|
void screen_line(int row, int coloff, int endcol, int clear_width, int flags);
|
||||||
|
120
src/screen.c
120
src/screen.c
@ -122,6 +122,7 @@ static int redrawing_for_callback = 0;
|
|||||||
static schar_T *current_ScreenLine;
|
static schar_T *current_ScreenLine;
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
static void may_update_popup_mask(int type);
|
||||||
static void update_popups(void);
|
static void update_popups(void);
|
||||||
#endif
|
#endif
|
||||||
static void win_update(win_T *wp);
|
static void win_update(win_T *wp);
|
||||||
@ -612,8 +613,9 @@ update_screen(int type_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
// Update popup_mask if needed.
|
// Update popup_mask if needed. This may set w_redraw_top and w_redraw_bot
|
||||||
type = may_update_popup_mask(type);
|
// in some windows.
|
||||||
|
may_update_popup_mask(type);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
updating_screen = TRUE;
|
updating_screen = TRUE;
|
||||||
@ -1014,17 +1016,19 @@ get_wcr_attr(win_T *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update "popup_mask" if needed.
|
* Update "popup_mask" if needed.
|
||||||
* Also recomputes the popup size and positions.
|
* Also recomputes the popup size and positions.
|
||||||
* Also updates "popup_visible".
|
* Also updates "popup_visible".
|
||||||
* If more redrawing is needed than "type_arg" a higher value is returned.
|
* Also marks window lines for redrawing.
|
||||||
*/
|
*/
|
||||||
int
|
static void
|
||||||
may_update_popup_mask(int type_arg)
|
may_update_popup_mask(int type)
|
||||||
{
|
{
|
||||||
int type = type_arg;
|
|
||||||
win_T *wp;
|
win_T *wp;
|
||||||
|
short *mask;
|
||||||
|
int line, col;
|
||||||
|
|
||||||
if (popup_mask_tab != curtab)
|
if (popup_mask_tab != curtab)
|
||||||
popup_mask_refresh = TRUE;
|
popup_mask_refresh = TRUE;
|
||||||
@ -1038,14 +1042,22 @@ may_update_popup_mask(int type_arg)
|
|||||||
if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
|
if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
|
||||||
popup_mask_refresh = TRUE;
|
popup_mask_refresh = TRUE;
|
||||||
if (!popup_mask_refresh)
|
if (!popup_mask_refresh)
|
||||||
return type;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to update the mask, something has changed.
|
||||||
popup_mask_refresh = FALSE;
|
popup_mask_refresh = FALSE;
|
||||||
popup_mask_tab = curtab;
|
popup_mask_tab = curtab;
|
||||||
|
|
||||||
popup_visible = FALSE;
|
popup_visible = FALSE;
|
||||||
vim_memset(popup_mask, 0, screen_Rows * screen_Columns * sizeof(short));
|
|
||||||
|
// If redrawing everything, just update "popup_mask".
|
||||||
|
// If redrawing only what is needed, update "popup_mask_next" and then
|
||||||
|
// compare with "popup_mask" to see what changed.
|
||||||
|
if (type >= SOME_VALID)
|
||||||
|
mask = popup_mask;
|
||||||
|
else
|
||||||
|
mask = popup_mask_next;
|
||||||
|
vim_memset(mask, 0, screen_Rows * screen_Columns * sizeof(short));
|
||||||
|
|
||||||
// Find the window with the lowest zindex that hasn't been handled yet,
|
// Find the window with the lowest zindex that hasn't been handled yet,
|
||||||
// so that the window with a higher zindex overwrites the value in
|
// so that the window with a higher zindex overwrites the value in
|
||||||
@ -1053,10 +1065,7 @@ may_update_popup_mask(int type_arg)
|
|||||||
popup_reset_handled();
|
popup_reset_handled();
|
||||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
while ((wp = find_next_popup(TRUE)) != NULL)
|
||||||
{
|
{
|
||||||
int top_off, bot_off;
|
int height_extra, width_extra;
|
||||||
int left_off, right_off;
|
|
||||||
short *p;
|
|
||||||
int line, col;
|
|
||||||
|
|
||||||
popup_visible = TRUE;
|
popup_visible = TRUE;
|
||||||
|
|
||||||
@ -1064,30 +1073,71 @@ may_update_popup_mask(int type_arg)
|
|||||||
if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
|
if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
|
||||||
popup_adjust_position(wp);
|
popup_adjust_position(wp);
|
||||||
|
|
||||||
// the position and size are for the inside, add the padding and
|
// the width and height are for the inside, add the padding and
|
||||||
// border
|
// border
|
||||||
top_off = wp->w_popup_padding[0] + wp->w_popup_border[0];
|
height_extra = wp->w_popup_padding[0] + wp->w_popup_border[0]
|
||||||
bot_off = wp->w_popup_padding[2] + wp->w_popup_border[2];
|
+ wp->w_popup_padding[2] + wp->w_popup_border[2];
|
||||||
left_off = wp->w_popup_padding[3] + wp->w_popup_border[3];
|
width_extra = wp->w_popup_padding[3] + wp->w_popup_border[3]
|
||||||
right_off = wp->w_popup_padding[1] + wp->w_popup_border[1];
|
+ wp->w_popup_padding[1] + wp->w_popup_border[1];
|
||||||
|
|
||||||
for (line = wp->w_winrow + top_off;
|
for (line = wp->w_winrow;
|
||||||
line < wp->w_winrow + wp->w_height + bot_off
|
line < wp->w_winrow + wp->w_height + height_extra
|
||||||
&& line < screen_Rows; ++line)
|
&& line < screen_Rows; ++line)
|
||||||
for (col = wp->w_wincol + left_off;
|
for (col = wp->w_wincol;
|
||||||
col < wp->w_wincol + wp->w_width + right_off
|
col < wp->w_wincol + wp->w_width + width_extra
|
||||||
&& col < screen_Columns; ++col)
|
&& col < screen_Columns; ++col)
|
||||||
{
|
mask[line * screen_Columns + col] = wp->w_zindex;
|
||||||
p = popup_mask + line * screen_Columns + col;
|
|
||||||
if (*p != wp->w_zindex)
|
|
||||||
{
|
|
||||||
*p = wp->w_zindex;
|
|
||||||
type = NOT_VALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
// Only check which lines are to be updated if not already
|
||||||
|
// updating all lines.
|
||||||
|
if (mask == popup_mask_next)
|
||||||
|
for (line = 0; line < screen_Rows; ++line)
|
||||||
|
{
|
||||||
|
int col_done = 0;
|
||||||
|
|
||||||
|
for (col = 0; col < screen_Columns; ++col)
|
||||||
|
{
|
||||||
|
int off = line * screen_Columns + col;
|
||||||
|
|
||||||
|
if (popup_mask[off] != popup_mask_next[off])
|
||||||
|
{
|
||||||
|
popup_mask[off] = popup_mask_next[off];
|
||||||
|
|
||||||
|
// The screen position "line" / "col" needs to be redrawn.
|
||||||
|
// Figure out what window that is and update w_redraw_top
|
||||||
|
// and w_redr_bot. Only needs to be done for each window
|
||||||
|
// line.
|
||||||
|
if (col >= col_done)
|
||||||
|
{
|
||||||
|
linenr_T lnum;
|
||||||
|
int line_cp = line;
|
||||||
|
int col_cp = col;
|
||||||
|
|
||||||
|
// find the window where the row is in
|
||||||
|
wp = mouse_find_win(&line_cp, &col_cp);
|
||||||
|
if (wp != NULL)
|
||||||
|
{
|
||||||
|
if (line_cp >= wp->w_height)
|
||||||
|
// In (or below) status line
|
||||||
|
wp->w_redr_status = TRUE;
|
||||||
|
// compute the position in the buffer line from the
|
||||||
|
// position on the screen
|
||||||
|
else if (mouse_comp_pos(wp, &line_cp, &col_cp,
|
||||||
|
&lnum))
|
||||||
|
// past bottom
|
||||||
|
wp->w_redr_status = TRUE;
|
||||||
|
else
|
||||||
|
redrawWinline(wp, lnum);
|
||||||
|
|
||||||
|
// This line is going to be redrawn, no need to
|
||||||
|
// check until the right side of the window.
|
||||||
|
col_done = wp->w_wincol + wp->w_width - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -9112,6 +9162,7 @@ screenalloc(int doclear)
|
|||||||
short *new_TabPageIdxs;
|
short *new_TabPageIdxs;
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
short *new_popup_mask;
|
short *new_popup_mask;
|
||||||
|
short *new_popup_mask_next;
|
||||||
#endif
|
#endif
|
||||||
tabpage_T *tp;
|
tabpage_T *tp;
|
||||||
static int entered = FALSE; /* avoid recursiveness */
|
static int entered = FALSE; /* avoid recursiveness */
|
||||||
@ -9196,6 +9247,7 @@ retry:
|
|||||||
new_TabPageIdxs = LALLOC_MULT(short, Columns);
|
new_TabPageIdxs = LALLOC_MULT(short, Columns);
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
new_popup_mask = LALLOC_MULT(short, Rows * Columns);
|
new_popup_mask = LALLOC_MULT(short, Rows * Columns);
|
||||||
|
new_popup_mask_next = LALLOC_MULT(short, Rows * Columns);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FOR_ALL_TAB_WINDOWS(tp, wp)
|
FOR_ALL_TAB_WINDOWS(tp, wp)
|
||||||
@ -9241,6 +9293,7 @@ give_up:
|
|||||||
|| new_TabPageIdxs == NULL
|
|| new_TabPageIdxs == NULL
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
|| new_popup_mask == NULL
|
|| new_popup_mask == NULL
|
||||||
|
|| new_popup_mask_next == NULL
|
||||||
#endif
|
#endif
|
||||||
|| outofmem)
|
|| outofmem)
|
||||||
{
|
{
|
||||||
@ -9264,6 +9317,7 @@ give_up:
|
|||||||
VIM_CLEAR(new_TabPageIdxs);
|
VIM_CLEAR(new_TabPageIdxs);
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
VIM_CLEAR(new_popup_mask);
|
VIM_CLEAR(new_popup_mask);
|
||||||
|
VIM_CLEAR(new_popup_mask_next);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -9353,6 +9407,7 @@ give_up:
|
|||||||
TabPageIdxs = new_TabPageIdxs;
|
TabPageIdxs = new_TabPageIdxs;
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
popup_mask = new_popup_mask;
|
popup_mask = new_popup_mask;
|
||||||
|
popup_mask_next = new_popup_mask_next;
|
||||||
vim_memset(popup_mask, 0, Rows * Columns * sizeof(short));
|
vim_memset(popup_mask, 0, Rows * Columns * sizeof(short));
|
||||||
popup_mask_refresh = TRUE;
|
popup_mask_refresh = TRUE;
|
||||||
#endif
|
#endif
|
||||||
@ -9421,6 +9476,7 @@ free_screenlines(void)
|
|||||||
VIM_CLEAR(TabPageIdxs);
|
VIM_CLEAR(TabPageIdxs);
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
VIM_CLEAR(popup_mask);
|
VIM_CLEAR(popup_mask);
|
||||||
|
VIM_CLEAR(popup_mask_next);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10027,7 +10083,7 @@ win_do_lines(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
// this doesn't work when tere are popups visible
|
// this doesn't work when there are popups visible
|
||||||
if (popup_visible)
|
if (popup_visible)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
#endif
|
#endif
|
||||||
|
80
src/testdir/popupbounce.vim
Normal file
80
src/testdir/popupbounce.vim
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
" Use this script to measure the redrawing performance when a popup is being
|
||||||
|
" displayed. Usage with gcc:
|
||||||
|
" cd src
|
||||||
|
" # Edit Makefile to uncomment PROFILE_CFLAGS and PROFILE_LIBS
|
||||||
|
" make reconfig
|
||||||
|
" ./vim --clean -S testdir/popupbounce.vim main.c
|
||||||
|
" gprof vim gmon.out | vim -
|
||||||
|
|
||||||
|
" using line contination
|
||||||
|
set nocp
|
||||||
|
|
||||||
|
" don't switch screens when quitting, so we can read the frames/sec
|
||||||
|
set t_te=
|
||||||
|
|
||||||
|
let winid = popup_create(['line1', 'line2', 'line3', 'line4'], {
|
||||||
|
\ 'line' : 1,
|
||||||
|
\ 'col' : 1,
|
||||||
|
\ 'zindex' : 101,
|
||||||
|
\ })
|
||||||
|
redraw
|
||||||
|
|
||||||
|
let start = reltime()
|
||||||
|
let framecount = 0
|
||||||
|
|
||||||
|
let line = 1.0
|
||||||
|
let col = 1
|
||||||
|
let downwards = 1
|
||||||
|
let col_inc = 1
|
||||||
|
let initial_speed = 0.2
|
||||||
|
let speed = initial_speed
|
||||||
|
let accel = 1.1
|
||||||
|
let time = 0.1
|
||||||
|
|
||||||
|
let countdown = 0
|
||||||
|
|
||||||
|
while 1
|
||||||
|
if downwards
|
||||||
|
let speed += time * accel
|
||||||
|
let line += speed
|
||||||
|
else
|
||||||
|
let speed -= time * accel
|
||||||
|
let line -= speed
|
||||||
|
endif
|
||||||
|
|
||||||
|
if line + 3 >= &lines
|
||||||
|
let downwards = 0
|
||||||
|
let speed = speed * 0.8
|
||||||
|
let line = &lines - 3
|
||||||
|
endif
|
||||||
|
if !downwards && speed < 1.0
|
||||||
|
let downwards = 1
|
||||||
|
let speed = initial_speed
|
||||||
|
if line + 4 > &lines && countdown == 0
|
||||||
|
let countdown = 50
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
let col += col_inc
|
||||||
|
if col + 4 >= &columns
|
||||||
|
let col_inc = -1
|
||||||
|
elseif col <= 1
|
||||||
|
let col_inc = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
call popup_move(winid, {'line': float2nr(line), 'col': col})
|
||||||
|
redraw
|
||||||
|
let framecount += 1
|
||||||
|
if countdown > 0
|
||||||
|
let countdown -= 1
|
||||||
|
if countdown == 0
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
let elapsed = reltimefloat(reltime(start))
|
||||||
|
echomsg framecount .. ' frames in ' .. string(elapsed) .. ' seconds, ' .. string(framecount / elapsed) .. ' frames/sec'
|
||||||
|
|
||||||
|
qa
|
6
src/ui.c
6
src/ui.c
@ -3251,6 +3251,10 @@ retnomove:
|
|||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Functions also used for popup windows.
|
||||||
|
#if defined(FEAT_MOUSE) || defined(FEAT_TEXT_PROP) || defined(PROTO)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the position in the buffer line from the posn on the screen in
|
* Compute the position in the buffer line from the posn on the screen in
|
||||||
@ -3347,7 +3351,7 @@ mouse_comp_pos(
|
|||||||
* Returns NULL when something is wrong.
|
* Returns NULL when something is wrong.
|
||||||
*/
|
*/
|
||||||
win_T *
|
win_T *
|
||||||
mouse_find_win(int *rowp, int *colp UNUSED)
|
mouse_find_win(int *rowp, int *colp)
|
||||||
{
|
{
|
||||||
frame_T *fp;
|
frame_T *fp;
|
||||||
win_T *wp;
|
win_T *wp;
|
||||||
|
@ -777,6 +777,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1517,
|
||||||
/**/
|
/**/
|
||||||
1516,
|
1516,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user