From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= Date: Wed, 27 Mar 2019 16:14:39 +0100 Subject: magnifier: Scale the sprite to match the current monitor scaling Compute the sprite texture scale (unfortunately using a workaround, based on mutter cursor size preferences, tying to figure out the closest texture integer scaling), and use this value to compute the scaling that should be applied to the sprite in order to match the current monitor scaling. Origin: https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/475 Applied-Upstream: no Forwarded: yes --- js/ui/layout.js | 24 ++++++++++++++++++++---- js/ui/magnifier.js | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/js/ui/layout.js b/js/ui/layout.js index d7f73dc..e53ff9d 100644 --- a/js/ui/layout.js +++ b/js/ui/layout.js @@ -974,22 +974,38 @@ var LayoutManager = GObject.registerClass({ return ws.get_work_area_for_monitor(monitorIndex); } + _findIndexForRect(x, y, width, height) { + let rect = new Meta.Rectangle({ + x: Math.floor(x), + y: Math.floor(y), + width: Math.ceil(x + width) - Math.floor(x), + height: Math.ceil(y + height) - Math.floor(y) + }); + return global.display.get_monitor_index_for_rect(rect); + } + // This call guarantees that we return some monitor to simplify usage of it // In practice all tracked actors should be visible on some monitor anyway findIndexForActor(actor) { let [x, y] = actor.get_transformed_position(); let [w, h] = actor.get_transformed_size(); - let rect = new Meta.Rectangle({ x, y, width: w, height: h }); - return global.display.get_monitor_index_for_rect(rect); + return this._findIndexForRect(x, y, w, h); } - findMonitorForActor(actor) { - let index = this.findIndexForActor(actor); + _findMonitorForIndex(index) { if (index >= 0 && index < this.monitors.length) return this.monitors[index]; return null; } + findMonitorForActor(actor) { + return this._findMonitorForIndex(this.findIndexForActor(actor)); + } + + findMonitorForPoint(x, y) { + return this._findMonitorForIndex(this._findIndexForRect(x, y, 1, 1)); + } + _queueUpdateRegions() { if (!this._updateRegionIdle) { const laters = global.compositor.get_laters(); diff --git a/js/ui/magnifier.js b/js/ui/magnifier.js index f4012de..f8d235f 100644 --- a/js/ui/magnifier.js +++ b/js/ui/magnifier.js @@ -46,6 +46,8 @@ var MouseSpriteContent = GObject.registerClass({ }, class MouseSpriteContent extends GObject.Object { _init() { super._init(); + this._scale = 1.0; + this._monitorScale = 1.0; this._texture = null; } @@ -53,7 +55,10 @@ var MouseSpriteContent = GObject.registerClass({ if (!this._texture) return [false, 0, 0]; - return [true, this._texture.get_width(), this._texture.get_height()]; + let width = this._texture.get_width() / this._scale; + let height = this._texture.get_height() / this._scale; + + return [true, width, height]; } vfunc_paint_content(actor, node, _paintContext) { @@ -70,6 +75,29 @@ var MouseSpriteContent = GObject.registerClass({ textureNode.add_rectangle(actor.get_content_box()); } + _textureScale() { + if (!this._texture) + return 1; + + /* This is a workaround to guess the sprite scale; while it works file + * in normal scenarios, it's not guaranteed to work in all the cases, + * and so we should actually add an API to mutter that will allow us + * to know the real spirte texture scaling in order to adapt it to the + * wanted one. */ + let avgSize = (this._texture.get_width() + this._texture.get_height()) / 2; + return Math.max (1, Math.floor (avgSize / Meta.prefs_get_cursor_size() + .1)); + } + + _recomputeScale() { + let scale = this._textureScale() / this._monitorScale; + + if (this._scale != scale) { + this._scale = scale; + return true; + } + return false; + } + get texture() { return this._texture; } @@ -84,7 +112,19 @@ var MouseSpriteContent = GObject.registerClass({ if (!oldTexture || !coglTexture || oldTexture.get_width() != coglTexture.get_width() || - oldTexture.get_height() != coglTexture.get_height()) + oldTexture.get_height() != coglTexture.get_height()) { + this._recomputeScale(); + this.invalidate_size(); + } + } + + get scale() { + return this._scale; + } + + set monitorScale(monitorScale) { + this._monitorScale = monitorScale; + if (this._recomputeScale()) this.invalidate_size(); } }); @@ -113,6 +153,8 @@ var Magnifier = class Magnifier extends Signals.EventEmitter { this._settingsInit(aZoomRegion); aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse); + this._updateContentScale(); + St.Settings.get().connect('notify::magnifier-active', () => { this.setActive(St.Settings.get().magnifier_active); }); @@ -120,6 +162,13 @@ var Magnifier = class Magnifier extends Signals.EventEmitter { this.setActive(St.Settings.get().magnifier_active); } + _updateContentScale() { + let monitor = Main.layoutManager.findMonitorForPoint(this.xMouse, + this.yMouse); + this._mouseSprite.content.monitorScale = monitor ? + monitor.geometry_scale : 1; + } + /** * showSystemCursor: * Show the system mouse pointer. @@ -256,6 +305,8 @@ var Magnifier = class Magnifier extends Signals.EventEmitter { this.xMouse = xMouse; this.yMouse = yMouse; + this._updateContentScale(); + let sysMouseOverAny = false; this._zoomRegions.forEach(zoomRegion => { if (zoomRegion.scrollToMousePos())