monaco-editor icon indicating copy to clipboard operation
monaco-editor copied to clipboard

[Bug] Mouse click incorrectly sets the caret position

Open janarvaez opened this issue 2 years ago • 7 comments

Reproducible in vscode.dev or in VS Code Desktop?

  • [X] Not reproducible in vscode.dev or VS Code Desktop

Reproducible in the monaco editor playground?

Monaco Editor Playground Code

const customElement = document.createElement('div');
customElement.style.height = '100%';
customElement.attachShadow({mode: 'open'});

const customContainer = document.createElement('div');
customContainer.style.height = '100%';
customElement.shadowRoot.append(customContainer);

document.getElementById('container').append(customElement);

const editorRef = monaco.editor.create(customContainer, {
	value: `let wrapper = document.createElement('span');
wrapper.setAttribute('class', 'wrapper');
let icon = document.createElement('span');
icon.setAttribute('class', 'icon');
icon.setAttribute('tabindex', 0);
let info = document.createElement('span');
info.setAttribute('class', 'info');`,
      language: 'javascript',
});


Reproduction Steps

No response

Actual (Problematic) Behavior

I created a MonacoEditor which has issues with highlighting text and setting the caret in the desired position when clicking with the mouse, and I can't figure out what's going on.

I added a few console logs as an example, and for instance, I get:

// log1
mouseX: 376
mouseColumn: 16

// log2
mouseX: 223
mouseColumn: 23

What could be interfering with the correct position of the caret in the editor? How could it be that a click further to the right return a lower column number? The deviation is not consistent or proportional either. If I click in the same place, I do get it in the same position. But clicking in one place can have +2 columns wrong, in another to the right have about +6 columns wrong, and further to the right the caret can be even positioned -7 columns in the other direction (like in the example above).

Expected Behavior

Clicking in the editor correctly positions the caret

Additional Context

No response

UPDATE: I found out the issue is when using the editor inside a shadowDOM

janarvaez avatar Jul 27 '22 11:07 janarvaez

Can you provide an example in the playground to reproduce your issue? Thanks!

hediet avatar Jul 27 '22 12:07 hediet

Hi @hediet ! Thanks for the quick reply. I managed to get something that has similar issues with minimum code. My case is not as drastic, so in the example the caret won't move from the beginning, in my actual code it does move but to a wrong position. You can notice that if you click and type, the internal position does get moved though. I am using StencilJS for my custom elements with shadow DOM, so it might work better in my code due to stencil adding polyfills and other stuff. Hope this helps

janarvaez avatar Jul 27 '22 13:07 janarvaez

I'm sorry, but we need an example in our playground to properly investigate this bug and to rule out that, for example, StencilJS polyfills cause this issue.

hediet avatar Jul 27 '22 13:07 hediet

If you paste the code I added above in the description into the javascript tab in the playground it will reproduce

janarvaez avatar Jul 27 '22 13:07 janarvaez

There are some references to problems with the caret in this other issue: https://github.com/microsoft/monaco-editor/issues/619

janarvaez avatar Jul 27 '22 14:07 janarvaez

@janarvaez Did you find a fix or workaround? I'm facing the same issue and using monaco inside a shadowDOM is a requirement for me

lucasMarioza avatar Sep 21 '22 13:09 lucasMarioza

@janarvaez Did you find a fix or workaround? I'm facing the same issue and using monaco inside a shadowDOM is a requirement for me

I have 2 workarounds.

  1. have the container outside the shadowRoot passed as children through a slot. This works fine since the slotted container is actually outside, but wrapped and styled inside the shadow.
  2. Wrap the whole editor inside an iframe, but depending on your setup, this could be harder to achieve (although isolating the editor in an iframe prevents other issues, like having multiple editors with different languages rendered at the same time).

janarvaez avatar Sep 21 '22 14:09 janarvaez

The workaround 1 worked but I figured it out my actual problem. I had one external style from an ancestor component(outside the shadowDOM) that was setting font-variant: tabular-nums. For some reason if monaco was rendered outside the shadowDOM this style was not an issue, and if it was inside the shadowDOM not even remeasureFonts fixed the issue.

I suppose that somehow it is not considering styles coming from outside the shadowDOM during the font measurements, or something like that.

In my case removing this style was not a problem, so I sticked with that solution.

lucasMarioza avatar Sep 22 '22 14:09 lucasMarioza

You have to copy the CSS:

https://microsoft.github.io/monaco-editor/playground.html?source=v0.31.0-dev.20211210#XQAAAALGAwAAAAAAAABBqQkHQ5NjdMjwa-jY7SIQ9S7DNlzs5W-mwj0fe1ZCDRFc9ws9XQE0SJE1jc2VKxhaLFIw9vEWSxW3yscw4v2XLo-p0hMWx6TqtaYiguu-Ze1HCMrFo1TCjVGPLT5Z218HFXAvjYXjnc4hbgy7_q9nUQtRSXnUgURv_VPhCo6sAVqG0SvKaimja1QTmOemgfjAuH_ZsUCJrQ9kkDea6E5DIvOgpUg8Ooz5Syokix-8PisT_x2GKQwtZuJNiwh956-PeqaTJ4k8hkyvfbg37hDRdTkRWeeKWq9q4P2C6uBqCCrfAy7P-n00brWG8lkiN4ccS5r8ULl1pUpRuJDP7zdVMAep1-DchoNbdET213RHBHVxWlx6CHzw8dh1lvqzo2kufoQB_uxBxksEVP0UwFz5iU9yuhoVLkKQsSNRournKCvrzTi5-6tfDYinGCQ8VTLeOCb-M6rygm1wbv8ERDUpXq-fh5Li29WFZhze9AxwemNMokQULMVZ5AE6SWgTlECMf2K5uZSM7B8Q4gPEzmdSyN496XEBYe6idvwdl_7z6SveXA7QVHE5fjzutgwSxFRp8jsp_--3nuA

hediet avatar Mar 13 '23 12:03 hediet

Hello @hediet ! Thanks for looking into this. Unfortunately, that doesn't solve the issue. I do have the css in my real project as I can properly render the full editor and it renders correctly, but the cursor position is still there. It is even worse when trying to select text, as the highlighted selection doesn't follow the cursor. In the link you sent, even if you added the css, the problem is still there for me. The only way to fix this right now is to remove the shadowRoot in the web-component, which is not great

janarvaez avatar Mar 16 '23 08:03 janarvaez

https://user-images.githubusercontent.com/127384873/225558155-74b4634c-1ecc-4416-b9c7-4225afabaf0e.mov

Please look at this reproduction video

janarvaezkng avatar Mar 16 '23 08:03 janarvaezkng

I also stumbled into this. It worked fine in Microsoft Edge versions prior to 110.0.1587.69 (and older Chrome versions). The culprit seems to be window.getComputedStyle(el, null).getPropertyValue('font'); returning an empty string now. See https://github.com/microsoft/vscode/blob/4c53c189a195c78a305ccce19d47341b9bee9baa/src/vs/editor/browser/controller/mouseTarget.ts#LL1037C12-L1037C12 @hediet can we reopen this issue?

sorinui avatar Mar 16 '23 09:03 sorinui

I can reproduce the bug in edge, but not chrome.

@sorinui can you look into this?

hediet avatar Mar 16 '23 11:03 hediet

🤔 I'm using Chrome 111.0.5563.64 on mac and the bug is there

janarvaezkng avatar Mar 16 '23 11:03 janarvaezkng

Disabling font-feature-settings: "liga" 0, "calt" 0; in the dev tools fixed the bug for me, but I'm not sure it will have anyother side effects image

lucasMarioza avatar Mar 16 '23 19:03 lucasMarioza

@lucasMarioza thanks for sharing this!

Enabling/disabling this rule actually changes if window.getComputedStyle(el, null).getPropertyValue('font'); returns an empty string or not (as @sorinui pointed out)

This really looks like a bug in chrome to me.

As a workaround, you can disable the font-feature-settings in the editor options.

hediet avatar Mar 20 '23 10:03 hediet

Has someone already raised a chrome issue? We have the same problem, but only on some computers

jogibear9988 avatar Mar 22 '23 12:03 jogibear9988

I created a chrome issue (cause after switch to 111 it also happens on my computer): https://bugs.chromium.org/p/chromium/issues/detail?id=1426792

jogibear9988 avatar Mar 22 '23 12:03 jogibear9988

I suggest you create a minimal reproducible example for them (not using monaco editor), demonstrating the issue that getPropertyValue('font') returns an empty string.

hediet avatar Mar 22 '23 12:03 hediet

I suggest you create a minimal reproducible example for them (not using monaco editor), demonstrating the issue that getPropertyValue('font') returns an empty string.

is this surely the cause of the issue?

jogibear9988 avatar Mar 22 '23 12:03 jogibear9988

duplicate: https://github.com/microsoft/monaco-editor/issues/3858

jogibear9988 avatar Mar 22 '23 18:03 jogibear9988

duplicate: #3858

@jogibear9988 #3858 is a duplicate of this one

janarvaezkng avatar Mar 23 '23 07:03 janarvaezkng

We analysed this issue on the Chrome side, details here. The code @sorinui mentioned above: https://github.com/microsoft/vscode/blob/4c53c189a195c78a305ccce19d47341b9bee9baa/src/vs/editor/browser/controller/mouseTarget.ts#LL1037C12-L1037C12 - fails in newer Chrome and Safari Technology Preview as the font property serialisation behaviour was tightened and is serialized as an empty string when shorthand properties are set that cannot be serialized into the longhand, revealing a problem with this code. The font that is sent to charWidthReader.getCharWidth(text.charAt(i), font) will not be identical to the one of the displayed text, as it will be missing the font-feature-settings styling. FF has the same serialisation behaviour - why the cursor positioning issue does not occur there is unclear.

drott avatar Mar 24 '23 19:03 drott

Thanks a lot for investigating!

Suggestion from @drott:

I suggest for the Monaco editor to change the implementation of their character width measurement to recreate the font in a more accurate way by using all longhand properties, or, as a temporary workaround, rebuild a font string by accessing the shorthands and compiling a longhand form from that.

hediet avatar Mar 24 '23 19:03 hediet

We analysed how this issue behaves in Chrome, Firefox, and Safari, looks like for Firefox Monaco editor is not accessing the font property for cursor positioning, that's why it is working correctly in Firefox, details here.

tursunova avatar Mar 27 '23 12:03 tursunova

FYI, we at Google are still seeing the same Chrome behavior, though in a much narrower set of circumstances, with v0.37.0 (and now also on 0.37.1). (The good news for us is that we've found a workaround for it. See the end of the note for details. But you'll probably still want to figure out what's going on.)

It's all working fine now on Macs. But selection continues to be broken on Windows. Here's a synopsis of what we're seeing:

  • On Windows, using Chrome 111.0.5563.147 or 112.0.5615.50, at normal resolution, the font metrics used for selection are narrower than those used to display the text. So near the ends of lines, particularly longer ones, the last few characters appear to be cut off from the selection. In fact, everything is selected just fine, it's just that the selection doesn't line up with the display so it's no longer WYSIWYG, which makes it essentially unusable.
  • If you change your resolution to 90% or 110% in these browsers, selection lines up with display like normal.
  • We've had a report that Chrome 111.0.5563.64 has no problem at 100% resolution.
  • Most interesting, if you reload the page the selection is drawn correctly.

Here's an example at 100% resolution (in Chrome 112.0.5615.50 on Windows) showing the problem: image

The same screen at 90%: image

And at 110%: image

The workaround we have discovered is to add the fontLigatures property to your IStandaloneEditorConstructionOptions:

const EDITOR_CONFIG: monaco.editor.IStandaloneEditorConstructionOptions = {
  ...,
  fontLigatures: '',
};

With that option set, selection is drawn correctly even on Windows.

leadpipe avatar Apr 17 '23 19:04 leadpipe

@hediet reopwn?

jogibear9988 avatar Apr 18 '23 05:04 jogibear9988

The change in https://github.com/microsoft/vscode/pull/178795/files is not setting font-feature-settings for the measurements, which may explain the difference in measurement vs. displayed text.

drott avatar Apr 18 '23 06:04 drott

I am experiencing this issue in my PayloadCMS instance which uses this package for their Code field. I'm running Chrome on MacOS. Is this the same issue or slightly different?

https://github.com/microsoft/monaco-editor/assets/44826828/17ac0a63-cd51-48f5-8d36-c333173c3ff8

TheDunco avatar Jun 02 '23 18:06 TheDunco

Situation as @TheDunco

cdllqos avatar Jun 21 '23 07:06 cdllqos