Вот мой код:
```py
from PyQt5.QtWidgets import QWidget, QApplication, QDesktopWidget
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QObject
from PyQt5.QtGui import QPainter, QColor
import sys
import threading
import queue
import platform


class BoxUpdater(QObject):
    """
    Worker для обновления отрисовки.
    """
    update_signal = pyqtSignal()

    def __init__(self, fps: int = 30):
        super().__init__()
        self.fps = fps
        self._is_running = False
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_signal.emit)

    def start_updating(self):
        """
        Запуск процесса обновления.
        """
        interval = max(1, int(1000 / self.fps))
        self.timer.start(interval)
        self._is_running = True

    def stop_updating(self):
        """
        Остановка процесса обновления.
        """
        self.timer.stop()
        self._is_running = False


class OverlayWidget(QWidget):
    """
    Виджет для отображения прямоугольников поверх полноэкранных приложений.
    """

    def __init__(self, fov_size: int = 512):
        super().__init__()

        # Устанавливаем специальные флаги для работы поверх полноэкранных приложений
        flags = Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool

        if platform.system() == "Windows":
            # Дополнительные флаги для Windows
            flags |= Qt.NoDropShadowWindowHint
            self.setWindowFlags(flags)
            # Важные атрибуты для работы поверх DirectX
            self.setAttribute(Qt.WA_TransparentForMouseEvents)
            self.setAttribute(Qt.WA_TranslucentBackground)
            self.setAttribute(Qt.WA_NoSystemBackground)
            self.setAttribute(Qt.WA_PaintOnScreen)
        else:
            # Для Linux и MacOS
            flags |= Qt.X11BypassWindowManagerHint
            self.setWindowFlags(flags)
            self.setAttribute(Qt.WA_TranslucentBackground)
            self.setAttribute(Qt.WA_NoSystemBackground)

        self.fov_size = fov_size
        self.boxes = []

        desktop = QDesktopWidget()
        screen_geometry = desktop.screenGeometry()

        self.workspace_x = (screen_geometry.width() - self.fov_size) // 2
        self.workspace_y = (screen_geometry.height() - self.fov_size) // 2
        self.setGeometry(screen_geometry)

    def paintEvent(self, event):
        """
        Событие отрисовки.
        """
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        # Отрисовка рамки workspace
        workspace_color = QColor(255, 255, 255, 50)
        painter.setPen(workspace_color)
        painter.drawRect(
            self.workspace_x,
            self.workspace_y,
            self.fov_size,
            self.fov_size
        )

        # Отрисовка боксов
        box_pen = QColor(0, 255, 0, 100)
        box_brush = QColor(0, 255, 0, 30)
        painter.setPen(box_pen)
        painter.setBrush(box_brush)

        for box in self.boxes:
            try:
                x = self.workspace_x + box['x']
                y = self.workspace_y + box['y']
                w = box['w']
                h = box['h']
                painter.drawRect(x, y, w, h)
            except (KeyError, TypeError) as e:
                print(f"Error drawing box: {e}")
                continue


class LitRectangle:
    """
    Оверлейное окно для отображения прямоугольников.
    """

    def __init__(self, fov_size: int = 512):
        self.fov_size = fov_size
        self.command_queue = queue.Queue()
        self.is_running = False
        self.qt_thread = None

    def _run_qt(self):
        """
        Запуск Qt в отдельном потоке
        """
        # Создаем QApplication
        app = QApplication.instance()
        if not app:
            app = QApplication(sys.argv)

        # Создаем виджет
        self.widget = OverlayWidget(self.fov_size)

        # Инициализация обновления
        self.updater = BoxUpdater()
        self.updater.update_signal.connect(self.widget.update)

        # Обработка команд
        self.command_timer = QTimer()
        self.command_timer.timeout.connect(self._process_commands)
        self.command_timer.start(16)  # ~60 fps для обработки команд

        self.widget.show()
        self.updater.start_updating()

        # Запускаем главный цикл
        app.exec_()

    def _process_commands(self):
        """
        Обработка команд из очереди
        """
        try:
            while True:  # Обрабатываем все команды в очереди
                command, data = self.command_queue.get_nowait()
                if command == 'set_boxes':
                    self.widget.boxes = data
                elif command == 'stop':
                    self.updater.stop_updating()
                    self.widget.close()
                    QApplication.instance().quit()
                    break
                self.command_queue.task_done()
        except queue.Empty:
            pass

    def activate(self, fps: int = 30):
        """
        Активация оверлея с заданной частотой обновления.
        """
        if self.is_running:
            return

        self.is_running = True
        self.qt_thread = threading.Thread(target=self._run_qt, daemon=True)
        self.qt_thread.start()

    def setBoxes(self, new_boxes: list):
        """
        Установить новые боксы для отрисовки.
        """
        if not isinstance(new_boxes, list):
            raise TypeError("new_boxes must be a list")
        self.command_queue.put(('set_boxes', new_boxes))

    def stop(self):
        """
        Остановка работы оверлея.
        """
        if self.is_running:
            self.command_queue.put(('stop', None))
            self.is_running = False
            if self.qt_thread:
                self.qt_thread.join(timeout=1.0)  # Ждем завершения потока
```

все равно оверлей пропадает, когда альттабаюсь на полноэкранную игру