最近吐槽了下火狐的个问题:近期换笔记本,发现火狐浏览器有个问题,吐槽下 - #9,来自 L_hiil ,我的插件只能临时修改下,但平白多加一次闪现,太碍眼了。但又用不爽其它Chromium类浏览器,于是把目光转移到 Zen 的 Glance,之前我试过,像大多数预览插件一样对链接识别并不在乎,因为一般用户也不在意,而我希望尽可能像 Arc Peek 那样无论链接在哪里都可预览。
通过 AI,自行修改了ZenGlanceChild.sys.mjs`,对于 closed 状态的 shadow root 还是不支持,不知道 Arc 是怎么实现的,有大佬知道么分享下
。
修改步骤
1、将"C:\Program Files\Zen Browser\browser\omni.ja" 这个文件复制到其它地方,用解压工具解压出来,
2、修改 "omni\actors\ZenGlanceChild.sys.mjs",直接用下面源码覆盖即可
源码
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
export class ZenGlanceChild extends JSWindowActorChild {
constructor() {
super();
this.mouseUpListener = this.handleMouseUp.bind(this);
this.mouseDownListener = this.handleMouseDown.bind(this);
this.clickListener = this.handleClick.bind(this);
}
async handleEvent(event) {
switch (event.type) {
case 'DOMContentLoaded':
await this.initiateGlance();
break;
case 'keydown':
this.onKeyDown(event);
break;
default:
}
}
async getActivationMethod() {
if (this._activationMethod === undefined) {
this._activationMethod = await this.sendQuery('ZenGlance:GetActivationMethod');
}
return this._activationMethod;
}
async getHoverActivationDelay() {
if (this._hoverActivationDelay === undefined) {
this._hoverActivationDelay = await this.sendQuery('ZenGlance:GetHoverActivationDelay');
}
return this._hoverActivationDelay;
}
async initiateGlance() {
this.mouseIsDown = false;
const activationMethod = await this.getActivationMethod();
if (activationMethod === 'mantain') {
this.contentWindow.addEventListener('mousedown', this.mouseDownListener);
this.contentWindow.addEventListener('mouseup', this.mouseUpListener);
this.contentWindow.document.removeEventListener('click', this.clickListener);
} else if (
activationMethod === 'ctrl' ||
activationMethod === 'alt' ||
activationMethod === 'shift'
) {
this.contentWindow.document.addEventListener('click', this.clickListener, { capture: true });
this.contentWindow.removeEventListener('mousedown', this.mouseDownListener);
this.contentWindow.removeEventListener('mouseup', this.mouseUpListener);
}
}
ensureOnlyKeyModifiers(event) {
return !(event.ctrlKey ^ event.altKey ^ event.shiftKey ^ event.metaKey);
}
openGlance(target) {
const url = target ?
(target.getAttribute('data-url') ||
(target.href.startsWith('/') ? window.location.protocol + target.href : target.href))
: null;
if (url && /^(mailto|tel|javascript):/.test(url.trim())) return;
const rect = target.getBoundingClientRect();
this.sendAsyncMessage('ZenGlance:OpenGlance', {
url,
clientX: rect.left,
clientY: rect.top,
width: rect.width,
height: rect.height,
});
}
handleMouseUp(event) {
if (this.hasClicked) {
event.preventDefault();
event.stopPropagation();
this.hasClicked = false;
}
this.mouseIsDown = null;
}
async handleMouseDown(event) {
const target = event.target.closest('A');
if (!target) {
return;
}
this.mouseIsDown = target;
const hoverActivationDelay = await this.getHoverActivationDelay();
this.contentWindow.setTimeout(() => {
if (this.mouseIsDown === target) {
this.hasClicked = true;
this.openGlance(target);
}
}, hoverActivationDelay);
}
handleClick(event) {
const anchorElement = event.composedPath().find(
node => node && node.nodeType === Node.ELEMENT_NODE && node.tagName === 'A'
);
//const anchorElement = event.composedPath().find(node => node instanceof HTMLAnchorElement);
const target = anchorElement ||
(event.target instanceof HTMLElement && (event.target.tagName === 'A' ? event.target : event.target.closest('A')));
if (this.ensureOnlyKeyModifiers(event) || event.button !== 0 || event.defaultPrevented) {
return;
}
const activationMethod = this._activationMethod;
if (activationMethod === 'ctrl' && !event.ctrlKey) {
return;
} else if (activationMethod === 'alt' && !event.altKey) {
return;
} else if (activationMethod === 'shift' && !event.shiftKey) {
return;
} else if (activationMethod === 'meta' && !event.metaKey) {
return;
} else if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') {
return;
}
// get closest A element
if (target) {
event.preventDefault();
event.stopPropagation();
this.openGlance(target);
}
}
onKeyDown(event) {
if (event.defaultPrevented || event.key !== 'Escape') {
return;
}
this.sendAsyncMessage('ZenGlance:CloseGlance', {
hasFocused: this.contentWindow.document.activeElement !== this.contentWindow.document.body,
});
}
}
3、修改后回到 "omni\" 目录,全选目录下的内容打包成 .zip,然后再重命名为 omni.ja
4、关闭 Zen 浏览器,用新的 omni.ja 覆盖掉原有的
5、重新打开 Zen 就可以了
修改后效果
b站视频评论区
IT之家文章下方的“大家在看”
这个虽然不能像我的插件那样自由调整和记住预览窗口的大小,但 Glance 不是基于窗口的,也就不会闪一下了,且能在全屏状态下使用,甚至分屏状态下,这里不得不赞一下 Zen 的分屏,分屏的数量比 Edge 多。
20250823更新:突然发现放错文件信息,真是心血来潮搞太晚搞眼花了 ![]()