diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index c550579d..8d61d8f6 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -89,7 +89,11 @@ class DisplayFloat extends Display { } } - async initialize(options, popupInfo, url, childrenSupported) { + setContentScale(scale) { + document.body.style.fontSize = `${scale}em`; + } + + async initialize(options, popupInfo, url, childrenSupported, scale) { await super.initialize(options); const {id, depth, parentFrameId} = popupInfo; @@ -99,6 +103,8 @@ class DisplayFloat extends Display { if (childrenSupported) { popupNestedInitialize(id, depth, parentFrameId, url); } + + this.setContentScale(scale); } } @@ -116,7 +122,8 @@ DisplayFloat._messageHandlers = new Map([ ['setContent', (self, {type, details}) => self.setContent(type, details)], ['clearAutoPlayTimer', (self) => self.clearAutoPlayTimer()], ['setCustomCss', (self, {css}) => self.setCustomCss(css)], - ['initialize', (self, {options, popupInfo, url, childrenSupported}) => self.initialize(options, popupInfo, url, childrenSupported)] + ['initialize', (self, {options, popupInfo, url, childrenSupported, scale}) => self.initialize(options, popupInfo, url, childrenSupported, scale)], + ['setContentScale', (self, {scale}) => self.setContentScale(scale)] ]); DisplayFloat.instance = new DisplayFloat(); diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 85f1f373..52e3a5bc 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -34,6 +34,8 @@ class Frontend extends TextScanner { url: popup.url }; + this._pageZoomFactor = 1.0; + this._contentScale = 1.0; this._orphaned = true; this._lastShowPromise = Promise.resolve(); } @@ -41,11 +43,14 @@ class Frontend extends TextScanner { async prepare() { try { await this.updateOptions(); + const {zoomFactor} = await apiGetZoom(); + this.onZoomChanged({newZoomFactor: zoomFactor}); window.addEventListener('resize', this.onResize.bind(this), false); yomichan.on('orphaned', () => this.onOrphaned()); yomichan.on('optionsUpdate', () => this.updateOptions()); + yomichan.on('zoomChanged', (e) => this.onZoomChanged(e)); chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this)); } catch (e) { this.onError(e); @@ -80,6 +85,11 @@ class Frontend extends TextScanner { this._orphaned = true; } + onZoomChanged({newZoomFactor}) { + this._pageZoomFactor = newZoomFactor; + this._updateContentScale(); + } + getMouseEventListeners() { return [ ...super.getMouseEventListeners(), @@ -90,6 +100,7 @@ class Frontend extends TextScanner { async updateOptions() { this.setOptions(await apiOptionsGet(this.getOptionsContext())); await this.popup.setOptions(this.options); + this._updateContentScale(); } async onSearchSource(textSource, cause) { @@ -183,6 +194,15 @@ class Frontend extends TextScanner { ); return this._lastShowPromise; } + + _updateContentScale() { + const contentScale = 1.0 / this._pageZoomFactor; // TODO : Use options + if (contentScale === this._contentScale) { return; } + + this._contentScale = contentScale; + this.popup.setContentScale(this._contentScale); + this.onResize(); + } } Frontend._windowMessageHandlers = new Map([ diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index c4f0c6ff..427172c6 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -41,7 +41,8 @@ class PopupProxyHost { ['containsPoint', ({id, x, y}) => this._onApiContainsPoint(id, x, y)], ['showContent', ({id, elementRect, writingMode, type, details}) => this._onApiShowContent(id, elementRect, writingMode, type, details)], ['setCustomCss', ({id, css}) => this._onApiSetCustomCss(id, css)], - ['clearAutoPlayTimer', ({id}) => this._onApiClearAutoPlayTimer(id)] + ['clearAutoPlayTimer', ({id}) => this._onApiClearAutoPlayTimer(id)], + ['setContentScale', ({id, scale}) => this._onApiSetContentScale(id, scale)] ])); } @@ -97,6 +98,11 @@ class PopupProxyHost { return popup.clearAutoPlayTimer(); } + async _onApiSetContentScale(id, scale) { + const popup = this._getPopup(id); + return popup.setContentScale(scale); + } + // Private functions _createPopupInternal(parentId, depth) { diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index ae0cffad..4cacee53 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -97,6 +97,11 @@ class PopupProxy { this._invokeHostApi('clearAutoPlayTimer', {id: this._id}); } + async setContentScale(scale) { + const id = await this._getPopupId(); + this._invokeHostApi('setContentScale', {id, scale}); + } + // Private _getPopupId() { diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 12a5c1c2..3c774f54 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -33,6 +33,7 @@ class Popup { this._visibleOverride = null; this._options = null; this._stylesheetInjectedViaApi = false; + this._contentScale = 1.0; this._container = document.createElement('iframe'); this._container.className = 'yomichan-float'; @@ -120,6 +121,13 @@ class Popup { } } + setContentScale(scale) { + this._contentScale = scale; + if (this._isInjectedAndLoaded) { + this._invokeApi('setContentScale', {scale}); + } + } + // Popup-only public functions setParent(parent) { @@ -225,7 +233,8 @@ class Popup { parentFrameId }, url: this.url, - childrenSupported: this._childrenSupported + childrenSupported: this._childrenSupported, + scale: this._contentScale }); resolve(); }); @@ -248,12 +257,14 @@ class Popup { Popup._getPositionForVerticalText ); + const scale = this._contentScale; const [x, y, width, height, below] = getPosition( elementRect, - Math.max(containerRect.width, optionsGeneral.popupWidth), - Math.max(containerRect.height, optionsGeneral.popupHeight), + Math.max(containerRect.width, optionsGeneral.popupWidth * scale), + Math.max(containerRect.height, optionsGeneral.popupHeight * scale), document.body.clientWidth, window.innerHeight, + scale, optionsGeneral, writingMode ); @@ -339,8 +350,8 @@ class Popup { } } - static _getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, optionsGeneral) { - let x = elementRect.left + optionsGeneral.popupHorizontalOffset; + static _getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral) { + let x = elementRect.left + optionsGeneral.popupHorizontalOffset * offsetScale; const overflowX = Math.max(x + width - maxWidth, 0); if (overflowX > 0) { if (x >= overflowX) { @@ -353,7 +364,7 @@ class Popup { const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below'); - const verticalOffset = optionsGeneral.popupVerticalOffset; + const verticalOffset = optionsGeneral.popupVerticalOffset * offsetScale; const [y, h, below] = Popup._limitGeometry( elementRect.top - verticalOffset, elementRect.bottom + verticalOffset, @@ -365,10 +376,10 @@ class Popup { return [x, y, width, h, below]; } - static _getPositionForVerticalText(elementRect, width, height, maxWidth, maxHeight, optionsGeneral, writingMode) { + static _getPositionForVerticalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral, writingMode) { const preferRight = Popup._isVerticalTextPopupOnRight(optionsGeneral.popupVerticalTextPosition, writingMode); - const horizontalOffset = optionsGeneral.popupHorizontalOffset2; - const verticalOffset = optionsGeneral.popupVerticalOffset2; + const horizontalOffset = optionsGeneral.popupHorizontalOffset2 * offsetScale; + const verticalOffset = optionsGeneral.popupVerticalOffset2 * offsetScale; const [x, w] = Popup._limitGeometry( elementRect.left - horizontalOffset,