Skip to content

Workaround for the webview positioning bug#137506

Merged
mjbvz merged 10 commits intomicrosoft:mainfrom
a-stewart:hacky-fix-for-webview-position
May 17, 2022
Merged

Workaround for the webview positioning bug#137506
mjbvz merged 10 commits intomicrosoft:mainfrom
a-stewart:hacky-fix-for-webview-position

Conversation

@a-stewart
Copy link
Copy Markdown
Contributor

@a-stewart a-stewart commented Nov 19, 2021

This is a small, hacky fix for #110450.

The webview can often end up in the incorrect position, because it's position is computed before the animation of the underlying view is finished, which results in the webview ending up where the animation started, not where it finished.

See a demo of the issue here:
demo

A good solution would involve either animating the overlay webview in the same way (tricky since we don't have information as to where the webview should end up) or moving the webview to be a child of the view container, so it's position is updated automatically.

As a more temporary fix, this CL adds a hack that simply asks the webview position to be updated every 40ms (25fps) for the next 200ms (length of the animation) which will cause the webview to "appear" to animate correctly into the correct position.

The works smoothly for me whilst testing, but there is a chance that it might be a bit slow on older hardware, however, even in that case, it would still be better than the current system which leaves the webview in the wrong place.

This should not be considered a fix for #110450, but will at least improve the situation and will never be worse than the current situation.

@a-stewart
Copy link
Copy Markdown
Contributor Author

Hi, @mjbvz - just a quick bump for this PR - was wondering if you might have some time to look into this?

@mjbvz
Copy link
Copy Markdown
Collaborator

mjbvz commented Mar 24, 2022

Sorry for the delay

This looks like a pretty hacky/brittle fix. I'm not sure what the proper fix is here but I don't think we can check this in as is

@a-stewart
Copy link
Copy Markdown
Contributor Author

a-stewart commented Mar 28, 2022

Hi,

Yeah, it's definitely not clean, but we have been running it for a few months without any issues.

There is a slightly less brittle version which moves it once after the animation is complete, but this version "appears" smoother to the user. I would suggest that whilst it isn't pretty, it is better than leaving the code base as-is since if a user ends up in a situation where this bug occurs there is no workaround and no way out of it, other than reloading vscode each time you want to expand or collapse the view.

In terms of the best solution, the cleanest option may be to remove the floating iframes used by webviews and instead position them as child elements of the view. However, I am not sure if there is historically a reason why they are floating instead of being children.

The other option could be to somehow share the animation with the webview before hand, rather than reactively moving it as we do currently. This is something I am happy to look into further, but I would rather know what kind of solutions you'd be interested before investing time in it.

@mjbvz
Copy link
Copy Markdown
Collaborator

mjbvz commented Mar 28, 2022

Yes the floating frames are required. They let us avoid having the iframes be re-parented, which destroys the frame contents

@boltex
Copy link
Copy Markdown

boltex commented Apr 5, 2022

@a-stewart @mjbvz Since a simple resize / refresh fixes the position, can it not be triggered automatically once after an expansion/contraction is finished? (200 ms after an expand/contract)

This would not animate smoothly, but at least when finished animating, the position would be corrected abruptly and somehow at least it would be somewhat fixed!

Just wondering... Thanks!

(Sorry not familiar enough yet with vscode's codebase to provide a pull request)

@a-stewart
Copy link
Copy Markdown
Contributor Author

a-stewart commented Apr 5, 2022

Since a simple resize / refresh fixes the position, can it not be triggered automatically once after an expansion/contraction is finished? (200 ms after an expand/contract)

Yes, that is what this PR did (I then updated it to do the same refresh a few times so it would "appear" to animate).

Rather than doing this (as it currently is):

			for (let i = 40; i <= 240; i += 20) {
				setTimeout(() => {
					this.layoutWebviewOverElement(element, dimension, /*animated*/ false);
				}, i);
			}

We can simply do:

			setTimeout(() => {
				this.layoutWebviewOverElement(element, dimension, /*animated*/ false);
			}, 200);

This will cause a reposition to be triggered 200ms later (after the animation is complete).

I think the cleanest option, may be to see if we can some how pass in the animation information to this message. As at the moment it has to act reactively and try and "catch up" with the underlying div. But if we knew where the div below as aiming at, we could animate it there properly.

@mjbvz
Copy link
Copy Markdown
Collaborator

mjbvz commented Apr 14, 2022

Yes I like that second approach better, even if it's still a hack. Can you update the PR to do that instead (but also make to cancel the timeout if the webview view is closed)

@boltex
Copy link
Copy Markdown

boltex commented Apr 17, 2022

@mjbvz Thanks for your consideration and approval of this suggestion! I'll let @a-stewart do the correction as I'm not knowledgable enough in vscode's code base to do so myself!

Thanks again! :)

@a-stewart
Copy link
Copy Markdown
Contributor Author

Updated as suggested.

This will result in there being a single "correction" made after the animation. So the underlying view and headers will move smoothly to the new position with the webview remaining where it is, and then once the animation is complete, the webview will jump in one step to the new location of the view.

mjbvz
mjbvz previously approved these changes May 5, 2022
Copy link
Copy Markdown
Collaborator

@mjbvz mjbvz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Let's test on insiders

@a-stewart
Copy link
Copy Markdown
Contributor Author

Is there something I need to do for Hygiene and Layering?

auto-merge was automatically disabled May 17, 2022 17:19

Head branch was pushed to by a user without write access

@a-stewart
Copy link
Copy Markdown
Contributor Author

Sorry for the delay - I have pulled in main to my local branch and run format document to hopefully fix the hygene issue.

}

public layoutWebviewOverElement(element: HTMLElement, dimension?: Dimension, clippingContainer?: HTMLElement) {
this.doLayoutWebviewOverElement(element.dimension, clippingContainer);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant to say element, dimension here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, sorry, updating and pushing

@mjbvz mjbvz enabled auto-merge (squash) May 17, 2022 23:32
@mjbvz mjbvz merged commit cf18990 into microsoft:main May 17, 2022
@a-stewart a-stewart deleted the hacky-fix-for-webview-position branch May 19, 2022 13:36
@github-actions github-actions bot locked and limited conversation to collaborators Jul 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants