Prevent Tab Focus Detection

Prevent websites from detecting tab focus without breaking functionality

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name        Prevent Tab Focus Detection
// @description Prevent websites from detecting tab focus without breaking functionality
// @version     2026.02.12
// @author      Claude Sonnet 4.5
// @grant       none
// @inject-into auto
// @run-at      document-start
// @match       *://*/*
// @namespace https://greasyfork.org/users/1519047
// ==/UserScript==

(function() {
    'use strict';

    // Store original functions
    const originalGetters = {};
    const originalMethods = {};

    // Override document visibility properties
    const overrideProperty = (obj, prop, fakeValue) => {
        const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
        if (descriptor && descriptor.get) {
            originalGetters[prop] = descriptor.get;
        }

        try {
            Object.defineProperty(obj, prop, {
                configurable: true,
                enumerable: true,
                get: function() {
                    return fakeValue;
                }
            });
        } catch(e) {
            console.debug('Tab focus prevention: Failed to override', prop, e);
        }
    };

    // Override all Page Visibility API properties (including vendor prefixes)
    overrideProperty(document, 'hidden', false);
    overrideProperty(document, 'visibilityState', 'visible');
    overrideProperty(document, 'webkitHidden', false);
    overrideProperty(document, 'webkitVisibilityState', 'visible');
    overrideProperty(document, 'mozHidden', false);
    overrideProperty(document, 'mozVisibilityState', 'visible');
    overrideProperty(document, 'msHidden', false);
    overrideProperty(document, 'msVisibilityState', 'visible');

    // Override hasFocus methods to always return true
    if (document.hasFocus) {
        originalMethods.documentHasFocus = document.hasFocus;
        document.hasFocus = function() {
            return true;
        };
    }

    if (window.hasFocus) {
        originalMethods.windowHasFocus = window.hasFocus;
        window.hasFocus = function() {
            return true;
        };
    }

    // Intercept visibility change events
    const interceptEvent = (e) => {
        e.stopImmediatePropagation();
    };

    // Only intercept Page Visibility API events (safest approach)
    const eventsToIntercept = [
        'visibilitychange',
        'webkitvisibilitychange',
        'mozvisibilitychange',
        'msvisibilitychange'
    ];

    eventsToIntercept.forEach(eventType => {
        window.addEventListener(eventType, interceptEvent, true);
        document.addEventListener(eventType, interceptEvent, true);
    });

    console.debug('Tab focus detection prevention active');
})();