From 480869c3d1d820b344d23989d2deae64a594869e Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Tue, 20 Sep 2022 21:06:39 -0400 Subject: Exclude documentElement from zoom calculation (#2227) * Exclude documentElement from zoom calculation * Add an option * Refactor zoom coordinate conversion functions * Convert zoom coordinates for text sources * Rename variable * Convert rect coordinate spaces * Handle shadow DOM --- ext/js/app/frontend.js | 1 + ext/js/app/popup.js | 58 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 9 deletions(-) (limited to 'ext/js/app') diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js index f3b925c3..de3eb7fd 100644 --- a/ext/js/app/frontend.js +++ b/ext/js/app/frontend.js @@ -395,6 +395,7 @@ class Frontend { this._textScanner.setOptions({ inputs: scanningOptions.inputs, deepContentScan: scanningOptions.deepDomScan, + normalizeCssZoom: scanningOptions.normalizeCssZoom, selectText: scanningOptions.selectText, delay: scanningOptions.delay, touchInputEnabled: scanningOptions.touchInputEnabled, diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js index 9ca2165d..8b62b92a 100644 --- a/ext/js/app/popup.js +++ b/ext/js/app/popup.js @@ -368,7 +368,7 @@ class Popup extends EventDispatcher { * `valid` is `false` for `PopupProxy`, since the DOM node is hosted in a different frame. */ getFrameRect() { - const {left, top, right, bottom} = this._frame.getBoundingClientRect(); + const {left, top, right, bottom} = this._getFrameBoundingClientRect(); return {left, top, right, bottom, valid: true}; } @@ -377,7 +377,7 @@ class Popup extends EventDispatcher { * @returns {Promise<{width: number, height: number, valid: boolean}>} The size and whether or not it is valid. */ async getFrameSize() { - const {width, height} = this._frame.getBoundingClientRect(); + const {width, height} = this._getFrameBoundingClientRect(); return {width, height, valid: true}; } @@ -680,12 +680,13 @@ class Popup extends EventDispatcher { * @returns {SizeRect} The calculated rectangle for where to position the popup. */ _getPosition(sourceRects, writingMode, viewport) { - const scale = this._contentScale; - const scaleRatio = this._frameSizeContentScale === null ? 1.0 : scale / this._frameSizeContentScale; - this._frameSizeContentScale = scale; + sourceRects = this._convertSourceRectsCoordinateSpace(sourceRects); + const contentScale = this._contentScale; + const scaleRatio = this._frameSizeContentScale === null ? 1.0 : contentScale / this._frameSizeContentScale; + this._frameSizeContentScale = contentScale; const frameRect = this._frame.getBoundingClientRect(); - const frameWidth = Math.max(frameRect.width * scaleRatio, this._initialWidth * scale); - const frameHeight = Math.max(frameRect.height * scaleRatio, this._initialHeight * scale); + const frameWidth = Math.max(frameRect.width * scaleRatio, this._initialWidth * contentScale); + const frameHeight = Math.max(frameRect.height * scaleRatio, this._initialHeight * contentScale); const horizontal = (writingMode === 'horizontal-tb' || this._verticalTextPosition === 'default'); let preferAfter; @@ -700,8 +701,8 @@ class Popup extends EventDispatcher { horizontalOffset = this._horizontalOffset2; verticalOffset = this._verticalOffset2; } - horizontalOffset *= scale; - verticalOffset *= scale; + horizontalOffset *= contentScale; + verticalOffset *= contentScale; let best = null; const sourceRectsLength = sourceRects.length; @@ -955,4 +956,43 @@ class Popup extends EventDispatcher { } return false; } + + /** + * Gets the bounding client rect for the frame element, with a coordinate conversion applied. + * @returns {DOMRect} The rectangle of the frame. + */ + _getFrameBoundingClientRect() { + return DocumentUtil.convertRectZoomCoordinates(this._frame.getBoundingClientRect(), this._container); + } + + /** + * Converts the coordinate space of source rectangles. + * @param {Rect[]} sourceRects The list of rectangles to convert. + * @returns {Rect[]} Either an updated list of rectangles, or `sourceRects` if no change is required. + */ + _convertSourceRectsCoordinateSpace(sourceRects) { + let scale = DocumentUtil.computeZoomScale(this._container); + if (scale === 1) { return sourceRects; } + scale = 1 / scale; + const sourceRects2 = []; + for (const rect of sourceRects) { + sourceRects2.push(this._createScaledRect(rect, scale)); + } + return sourceRects2; + } + + /** + * Creates a scaled rectangle. + * @param {Rect} rect The rectangle to scale. + * @param {number} scale The scale factor. + * @returns {Rect} A new rectangle which has been scaled. + */ + _createScaledRect(rect, scale) { + return { + left: rect.left * scale, + top: rect.top * scale, + right: rect.right * scale, + bottom: rect.bottom * scale + }; + } } -- cgit v1.2.3