您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Make website completely invisible to the user switching to another window or tab. May break some websites.
// ==UserScript== // @name Sabotage Window/Tab Switch Visibility // @description Make website completely invisible to the user switching to another window or tab. May break some websites. // @author owowed <[email protected]> // @version 0.0.3 // @namespace util.owowed.moe // @license GPL-3.0-or-later // @match *://*/* // @grant unsafeWindow // @run-at document-start // @copyright All rights reserved. Licensed under GPL-3.0-or-later. View license at https://spdx.org/licenses/GPL-3.0-or-later.html // ==/UserScript== !function () { /* Disable focus and blur event of document and window */ const windowProto = globalThis.unsafeWindow ?? window; console.log("Sabotage Window/Tab Switch Visibility is executing..."); disableFocusBlurEvent(Document.prototype); disableFocusBlurEvent(windowProto); function disableFocusBlurEvent(objPrototype) { const eventBlocklist = ["focus", "blur"]; for (const event of eventBlocklist) { defineGetterSetter(objPrototype, `on${event}`, { set: () => undefined, }); } const oldEventListener = objPrototype.addEventListener; objPrototype.addEventListener = function (event, ...args) { if (eventBlocklist.includes(event)) return; oldEventListener.call(this, event, ...args); } } /* Disable Page Visibility API */ defineGetterSetter(Document.prototype, "hidden", { get: () => false }); defineGetterSetter(Document.prototype, "visibilityState", { get: () => "visible" }); document.addEventListener("visibilitychange", function(e) { e.stopImmediatePropagation(); }, true); /* Partially disable blur and focus event (and other events) of element */ const safeBoxSize = 800; const elementOldEventListener = Element.prototype.addEventListener; const eventBlocklist = [ "blur", "focus", "mouseleave", "hasFocus" ]; // Element.on{event} properties, like Element.onfocus, Element.onblur etc. for (const event of eventBlocklist) { if (event == "hasFocus") continue; let registered = false; defineGetterSetter(Element.prototype, `on${event}`, { set(callback) { if (!registered) { this.addEventListener(event, callback) registered = true; } } }); } // override Element.addEventListener Element.prototype.addEventListener = function (event, callback, ...args) { if (eventBlocklist.includes(event)) { const elem = this; elementOldEventListener.call(this, event, (...eventArgs) => { const clientRect = elem.getBoundingClientRect(); if (clientRect.width >= safeBoxSize || clientRect.height >= safeBoxSize) { return; } callback(...eventArgs); }, ...args); } else elementOldEventListener.call(this, event, callback, ...args); }; /* Disable CSS prefers-reduced-motion for JavaScript */ const windowOldMatchMedia = windowProto.matchMedia; windowProto.matchMedia = function (matchMedia, ...args) { if (matchMedia.includes("prefers-reduced-motion") && matchMedia.includes("reduce")) { return false; } return windowOldMatchMedia.call(this, matchMedia, ...args); } console.log("Sabotage Window/Tab Switch Visibility executed"); }(); function defineGetterSetter(proto, property, { get, set } = {}) { Object.defineProperty(proto, property, { get, set, enumerable: true, configurable: true }) }