xterm.js icon indicating copy to clipboard operation
xterm.js copied to clipboard

Character size computation is affected by CSS transforms

Open cebamps opened this issue 5 years ago • 2 comments

When a Terminal is opened in an element subject to CSS transformations such as scale or rotate, the computation of the character size is affected by that transformation, which is wrong because the rendering should be transform-agnostic.

As a result, this makes the integration of Xterm.js into reveal.js slides render incorrectly when the slides are scaled down to fit the browser viewport.

Changing the measurement method in CharSizeService to use getComputedStyle instead of getBoundingClientRect makes the computation independent of CSS transforms.

Details

  • Browser and browser version: Firefox 69.0 and Chromium 77.0
  • OS version: Arch Linux
  • xterm.js version: current master (6311076)

Steps to reproduce

  1. Add style="transform: rotate(90deg);" to the <body> tag in demo/index.html
  2. Notice that character boxes in the demo have the wrong dimensions

Workaround

With the rotate(90deg) CSS transform Xterm.js renders character cells with the width and height swapped around: getBoundingClientRect

The cause is in the measurement methods in CharSizeService: it uses getBoundingClientRect, which returns the size of the bounding box after CSS transforms. https://github.com/xtermjs/xterm.js/blob/631107698ec1f28577101cc570540f097a83af68/src/browser/services/CharSizeService.ts#L71-L86

My understanding is that the rendering of the terminal should not be affected by said transforms. And indeed, replacing the geometry definition in the code above with (POC)

    const computedStyle = getComputedStyle(this._measureElement);
    const geometry = {
      height: Number(computedStyle.getPropertyValue('height').replace('px', '')),
      width: Number(computedStyle.getPropertyValue('width').replace('px', '')),
    }

yields a correct rendering: getComputedStyle

Note that my proof-of-concept fix above may be insufficient in cases where the element or its parent are display: none.

cebamps avatar Oct 20 '19 18:10 cebamps

@cebamps the workaround seems reasonable.

Note that my proof-of-concept fix above may be insufficient in cases where the element or its parent are display: none.

I don't think this should matter.

Tyriar avatar Oct 21 '19 21:10 Tyriar

I am not really able to reproduce. The selection with cursor is broken when you rotate the terminal.

leomoty avatar Oct 22 '19 21:10 leomoty

Still reproduces:

image

Tyriar avatar Dec 15 '22 15:12 Tyriar

Oh well, wasnt aware of this - also needs to be changed in #4605.

jerch avatar Aug 01 '23 13:08 jerch