-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Implement popupmenu as a floating grid internally to reduce flicker #9530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ping @Shougo what is the typical situation for vim/vim@ae65438, is it multiple |
42217df
to
a9a74d7
Compare
src/nvim/compositor.c
Outdated
@@ -0,0 +1,369 @@ | |||
// This is an open source non-commercial project. Dear PVS-Studio, please check |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name it ui_compositor.c
, so it is grouped with ui.c
and ui_bridge.c
? And the prefix could be uicomp_
. This helps discover the project structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, lets do that.
src/nvim/ui.c
Outdated
@@ -338,6 +359,18 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, | |||
} | |||
} | |||
|
|||
void ui_composed_call_raw_line(Integer draw_grid, Integer row, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't "composite" the more common phrasing rather than "composed"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, but "composed" is a passive/past tense as in "the UI is (being) composed" or "after the line was composed"
src/nvim/ui.c
Outdated
@@ -85,21 +86,25 @@ static char uilog_last_event[1024] = { 0 }; | |||
// | |||
// See http://stackoverflow.com/a/11172679 for how it works. | |||
#ifdef _MSC_VER | |||
# define UI_CALL(funname, ...) \ | |||
# define UI_CALL_CND(CND, funname, ...) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does CND mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
condition, maybe _IF
is better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW we use cond
in a few places.
# define UI_CALL_IF(cond, ...
Yes. I will test the branch later. |
And another thing: using compositior for pum also make possible things like this: Probably not practially useful for anything (except I guess providing useful context once in a blue moon), but maybe it can help make up for the lack of |
@bfredl I have tested below script with the branch. " save this as complete_flicker.vim
" vim -u complete_flicker.vim -c "startinsert"
let s:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
let s:last_tick = []
function! s:current_tick()
return [b:changedtick, getcurpos()]
endfunction
function! s:check_changes(...)
let l:current_tick = s:current_tick()
if s:last_tick != l:current_tick
let s:last_tick = l:current_tick
call s:on_changed()
endif
endfunction
function! s:start_check_changes_timer()
let s:last_tick = []
let s:check_change_timer = timer_start(30, function('s:check_changes'), {'repeat': -1})
endfunction
function! s:stop_check_changes_timer()
if exists('s:check_change_timer')
call timer_stop(s:check_change_timer)
unlet s:check_change_timer
endif
endfunction
function! s:on_changed()
if mode() != 'i'
return
endif
setlocal completeopt-=longest
setlocal completeopt+=menuone
setlocal completeopt-=menu
setlocal completeopt+=noselect
call complete(1, s:months)
endfunction
autocmd TextChangedI * call s:check_changes()
autocmd InsertEnter * call s:start_check_changes_timer()
autocmd InsertLeave * call s:stop_check_changes_timer() In the branch, narrowing flicker is gone, but press backspace is more flicker than master of neovim. |
Thanks, I will investigate. |
Actually, it seems to randomly happen for both typing and backspace (but not all of either). |
@Shougo I think at least some of the flicker here is fundamental, not related to this patch. Because if you press a key that changes the pum, and then 0-30ms later a timer will change the pum back again, there will be flicker for up to 30ms. Adding this line fixes it:
Does nvim behave subtly different than vim for the behavior of autocmds, perhaps? |
But I changed timer to manually invoked |
Hmm state management in
|
Did the defer for only undisplay for now, probably enough. @Shougo please try it again. |
I have tested the latest version. |
Issue: invoke the popupmenu with lots of items so it covers the entire the height of the screen. Now do |
vim issue: vim/vim#3838 |
The problem is fixed in Vim. |
98c2366
to
171e446
Compare
b650143
to
6426cd1
Compare
I have tested the branch, and it is faster completion than master. |
8f0a227
to
1a03769
Compare
Initially we will use this for the popupmenu, floating windows will follow soon NB: writedelay + compositor is weird, we need more flexible redraw introspection.
This makes it possible for the compositor to compare the old pum with the new position, and only clear what is necessary.
Many of these are handled by the compositor. Check that it causes no glitches.
Made some simplifications to the dispatching logic. A single |
Seems like you have a bug. After filtering spaces between items and metadata disappear. Nice to see this pull request. I thought it would never be fixed! |
@purpleP yes, the metadata seems to be shifted to the left one cell. Thanks for noticing, I will fix it. |
popupmenu: fix alignment of kind and extra after #9530
Extract the "compositor" layer from #6619. This allows us to draw the popupmenu on a separate grid rather than on the default grid, even for TUI use.
Attempt to eliminate flicker in all these cases:
complete()
call or something (corresponding to vim/vim@ae65438, tested now)Also
update_screen(NOT_VALID)
should never be needed to redraw the text under the pum, rather the cached contents is resent fromdefault_grid
.Note: in principle this will enable two connected UI:s, one using
ext_popupmenu
and the other using the builtin popupmenu, at the same time. This will need some other refactors though.Note 2: this should reduce the bookkeeping in
edit.c
for pum redraws (ideally all commented code can be removed, but needs more testing). This will lower the bar forex_getln.c
also using the pum instead of statusline wildmenu for completions. It will need to compute position differently, but apart from that it would be able to usepum_display
andpum_undisplay
without thinking about window redraws at all.fixes #9542.