thecyberd3m0n / Generic Focus Listeners Override

// ==UserScript==
// @namespace     https://openuserjs.org/users/thecyberd3m0n
// @name          Generic Focus Listeners Override
// @description   Disables focus-related events for any websites. Makes minimizing, hiding
// or switching to another tab undetectable by website. Work only on init
// @copyright     2024, thecyberd3m0n (https://openuserjs.org/users/thecyberd3m0n)
// @license       MIT
// @version       0.0.1
// @grant none
// ==/UserScript==

// ==OpenUserJS==
// @author thecyberd3m0n
// ==/OpenUserJS==

(function() {
    'use strict';
    // Override the properties directly on the window object
    
    // anti-blur-detection
    
    const blockedEvents = ["blur", "visibilitychange", "focusout"];

    const trackedListeners = new Map();

    function trackListener(target, type, listener) {
        if (!trackedListeners.has(target)) {
            trackedListeners.set(target, new Map());
        }
        const targetListeners = trackedListeners.get(target);
        if (!targetListeners.has(type)) {
            targetListeners.set(type, new Set());
        }
        targetListeners.get(type).add(listener);
    }

    function removeTrackedListener(target, type) {
        const targetListeners = trackedListeners.get(target);
        if (targetListeners && targetListeners.has(type)) {
            targetListeners.get(type).forEach(listener => {
                target.removeEventListener(type, listener);
                console.log(`[TamperMonkey] Removed listener for "${type}" on`, target);
            });
            targetListeners.delete(type);
        }
    }

    const originalAddEventListener = EventTarget.prototype.addEventListener;
    EventTarget.prototype.addEventListener = function(type, listener, options) {
        if (blockedEvents.includes(type)) {
            console.warn(`[TamperMonkey] Blocking addition of listener for "${type}" on`, this);
            trackListener(this, type, listener); // Track the listener even if blocked
            return;
        }
        originalAddEventListener.call(this, type, listener, options);
    };

    const originalRemoveEventListener = EventTarget.prototype.removeEventListener;
    EventTarget.prototype.removeEventListener = function(type, listener, options) {
        if (trackedListeners.has(this) && trackedListeners.get(this).has(type)) {
            trackedListeners.get(this).get(type).delete(listener);
        }
        originalRemoveEventListener.call(this, type, listener, options);
    };

    function cleanupBlockedListeners() {
        trackedListeners.forEach((typeListeners, target) => {
            blockedEvents.forEach(eventType => {
                if (typeListeners.has(eventType)) {
                    removeTrackedListener(target, eventType);
                }
            });
        });
    }

    cleanupBlockedListeners();

})();