microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
162.47k stars 28.63k forks source link

Decorations flickering on editor change #136241

Open memeplex opened 2 years ago

memeplex commented 2 years ago

Does this issue occur when all extensions are disabled?: Yes

I've recently been trying to optimize an extension that decorates [[...]] wikilinks in markdown documents. Every time I switched between editors a very noticeable flickering happened because of the syntax rehighlighting of the editor and, not so shortly after that, a delayed repainting of decorations. I checked other similar extensions and the pattern was always the same. It's even suggested in this "official" example: https://github.com/microsoft/vscode-extension-samples/blob/main/decorator-sample/src/extension.ts. There are two problems:

  1. The suggested delay of 500ms might be reasonable for in-editor changes but for editor switching it produces this: https://github.com/foambubble/foam/issues/805#issuecomment-954604703.
  2. Even with no throttling at all and with precalculation and caching of document decorations (that I roughly implemented here https://github.com/svsool/vscode-memo/pull/479) there is the same repainting glitch, although it's less obvious.

The second point is likely the hard one because it might be due to a more structural limit of the design. Why is VSCode triggering document-wise updates of decorations in unchanged documents? From the perspective of the extension author, is there any way to do that update incrementally, some knowledge of damaged/exposed chunks?

N.B. in the above cases extending the syntax was also problematic, for example because of the need to distinctively decorate valid and invalid links. Even if the syntax extension approach were effective here, the point still stands that decorations seem ill-suited for anything but small documents and even in those documents they produce visual artifacts on editor switching.

memeplex commented 2 years ago

This is an interesting example that shows the issue with three different extensions that use decorations with different delays:

https://user-images.githubusercontent.com/2845433/139742980-adec368d-da44-4f02-a271-172091b7bed2.mov

(the strikethrough effect is kind of cool though, like it's striking the word through XD)

alexdima commented 2 years ago

You are correct, the current approach to text editor decorations is to clear them when the text model is detached from the code editor (i.e. when switching tabs). Here is how decorations work internally:

I am not quite sure how we could improve things, perhaps by having a "persistent" property or something on these decorations that should survive across detaching / re-attaching a text model to a code editor.

memeplex commented 2 years ago

Thank you very much for the detailed answer @alexdima, I understand your points, I'm giving a heads up to extension developers that I believe may be interested in this.

memeplex commented 2 years ago

One thing that may be changed in any case is the reference example: the problem is made worse because extension developers may be copying a recipe that delays redecoration by 500ms even on editor switch.

alexdima commented 2 years ago

@memeplex I agree that the example is flawed, as it artificially delays computing decorations when switching editors. Would you be willing to contribute a PR to improve it?

memeplex commented 2 years ago

Sure @alexdima I'm pretty busy right now but I'll give it a try in a few days.

memeplex commented 2 years ago

@alexdima please see https://github.com/microsoft/vscode-extension-samples/pull/535/files. I'm not sure if there is any advantage in using a timeout of 0 (vs directly calling the refresh as I did).

yg-i commented 3 months ago

One thing that may be changed in any case is the reference example: the problem is made worse because extension developers may be copying a recipe that delays redecoration by 500ms even on editor switch.

Does calling setDecorations immediately upon active editor change [1] actually eliminate the 500ms delay?

If I understand the exchange correctly, and if my own testing is reliable, the 500ms or so delay appears to be unavoidable, at least as things currently stand?

[1] as in:

vscode.window.onDidChangeActiveTextEditor( (ed) => {ed.setDecorations(....)} )
yg-i commented 3 months ago

Also, I noticed that vscode's own inlay parameter hints (which I've read are also implemented using decorations) do persist across active editor change, and are unaffected by the 500ms delay. See this gif demonstration and notice how the 'num' inlay parameter hint in the func() call persists across editor changes.

2024_0608_0310_06 (Extraneous Vole)

Is there a way for extension developers to simulate the effect of persistent decorations?

1nVitr0 commented 1 week ago

A persistent property would be great. I use decorations to hide tokens and passwords in the Censitive Extension, and have always been annoyed by the delay (see https://github.com/1nVitr0/plugin-vscode-censitive/issues/50). I have restrained myself from opening an issue as hiding the document's contents until all decorations are ready just doesn't make sense. But being able to make certain decorations persistent would at least remove the delay when switching between already opened editors.