monaco-editor: [Bug] Mouse click incorrectly sets the caret position

Reproducible in vscode.dev or in VS Code Desktop?

  • 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


Edit by @hediet: Check here for verification steps

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 33 (9 by maintainers)

Commits related to this issue

Most upvoted comments

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.

@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.

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.

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

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.

@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 Did you find a fix or workaround? I’m facing the same issue and using monaco inside a shadowDOM is a requirement for me