171 lines
5.3 KiB
Python
171 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
import sys
|
|
import json
|
|
import signal
|
|
import os
|
|
from PyQt5.QtCore import Qt, QUrl, QTimer
|
|
from PyQt5.QtWidgets import (
|
|
QApplication, QMainWindow, QSystemTrayIcon, QMenu, QAction,
|
|
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
|
QComboBox, QPushButton, QMessageBox
|
|
)
|
|
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEnginePage, QWebEngineSettings
|
|
from PyQt5.QtGui import QColor, QIcon
|
|
|
|
CONFIG_PATH = os.path.expanduser("~/.config/hudfx-lnx/config.json")
|
|
|
|
|
|
def load_config():
|
|
if os.path.exists(CONFIG_PATH):
|
|
with open(CONFIG_PATH) as f:
|
|
return json.load(f)
|
|
return {"url": "", "screen_index": 0}
|
|
|
|
|
|
def save_config(config):
|
|
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True)
|
|
with open(CONFIG_PATH, "w") as f:
|
|
json.dump(config, f, indent=2)
|
|
|
|
|
|
class Overlay(QMainWindow):
|
|
def __init__(self, url, screen):
|
|
super().__init__()
|
|
self.setWindowFlags(
|
|
Qt.FramelessWindowHint |
|
|
Qt.WindowStaysOnTopHint |
|
|
Qt.Tool |
|
|
Qt.WindowTransparentForInput
|
|
)
|
|
self.setAttribute(Qt.WA_TranslucentBackground)
|
|
|
|
view = QWebEngineView()
|
|
profile = QWebEngineProfile(view)
|
|
page = QWebEnginePage(profile, view)
|
|
view.setPage(page)
|
|
view.page().setBackgroundColor(QColor(0, 0, 0, 0))
|
|
view.page().setAudioMuted(False)
|
|
|
|
settings = view.page().settings()
|
|
settings.setAttribute(QWebEngineSettings.PlaybackRequiresUserGesture, False)
|
|
settings.setAttribute(QWebEngineSettings.JavascriptEnabled, True)
|
|
|
|
view.load(QUrl(url))
|
|
self.setCentralWidget(view)
|
|
self.setGeometry(screen.geometry())
|
|
self.show()
|
|
|
|
|
|
class SettingsDialog(QDialog):
|
|
def __init__(self, config, screens, parent=None):
|
|
super().__init__(parent)
|
|
self.setWindowTitle("HudFX Settings")
|
|
self.setMinimumWidth(420)
|
|
self.config = config
|
|
|
|
layout = QVBoxLayout(self)
|
|
|
|
layout.addWidget(QLabel("Overlay URL:"))
|
|
self.url_input = QLineEdit(config.get("url", ""))
|
|
self.url_input.setPlaceholderText("https://...")
|
|
layout.addWidget(self.url_input)
|
|
|
|
layout.addWidget(QLabel("Display monitor:"))
|
|
self.screen_combo = QComboBox()
|
|
for i, screen in enumerate(screens):
|
|
s = screen.size()
|
|
name = f"Monitor {i + 1} — {s.width()}x{s.height()} ({screen.name()})"
|
|
self.screen_combo.addItem(name)
|
|
self.screen_combo.setCurrentIndex(config.get("screen_index", 0))
|
|
layout.addWidget(self.screen_combo)
|
|
|
|
buttons = QHBoxLayout()
|
|
save_btn = QPushButton("Save")
|
|
cancel_btn = QPushButton("Cancel")
|
|
save_btn.clicked.connect(self.accept)
|
|
cancel_btn.clicked.connect(self.reject)
|
|
buttons.addWidget(save_btn)
|
|
buttons.addWidget(cancel_btn)
|
|
layout.addLayout(buttons)
|
|
|
|
def get_values(self):
|
|
return {
|
|
"url": self.url_input.text().strip(),
|
|
"screen_index": self.screen_combo.currentIndex(),
|
|
}
|
|
|
|
|
|
class TrayApp:
|
|
def __init__(self, app):
|
|
self.app = app
|
|
self.config = load_config()
|
|
self.overlay = None
|
|
|
|
self.tray = QSystemTrayIcon()
|
|
self.tray.setToolTip("HudFX Overlay")
|
|
|
|
icon = QIcon.fromTheme("video-display")
|
|
if icon.isNull():
|
|
icon = QIcon.fromTheme("preferences-desktop-display")
|
|
self.tray.setIcon(icon)
|
|
|
|
self.menu = QMenu()
|
|
|
|
self.toggle_action = QAction("Start overlay")
|
|
self.toggle_action.triggered.connect(self.toggle_overlay)
|
|
self.menu.addAction(self.toggle_action)
|
|
|
|
self.settings_action = QAction("Settings...")
|
|
self.settings_action.triggered.connect(self.open_settings)
|
|
self.menu.addAction(self.settings_action)
|
|
|
|
self.menu.addSeparator()
|
|
|
|
self.quit_action = QAction("Quit")
|
|
self.quit_action.triggered.connect(self.quit)
|
|
self.menu.addAction(self.quit_action)
|
|
|
|
self.tray.setContextMenu(self.menu)
|
|
self.tray.show()
|
|
|
|
self.toggle_overlay()
|
|
|
|
def toggle_overlay(self):
|
|
if self.overlay:
|
|
self.overlay.close()
|
|
self.overlay = None
|
|
self.toggle_action.setText("Start overlay")
|
|
else:
|
|
url = self.config.get("url", "").strip()
|
|
if not url:
|
|
QMessageBox.warning(None, "HudFX", "No URL set. Open Settings first.")
|
|
return
|
|
idx = self.config.get("screen_index", 0)
|
|
screens = self.app.screens()
|
|
screen = screens[idx] if idx < len(screens) else self.app.primaryScreen()
|
|
self.overlay = Overlay(url, screen)
|
|
self.toggle_action.setText("Stop overlay")
|
|
|
|
def open_settings(self):
|
|
dialog = SettingsDialog(self.config, self.app.screens())
|
|
if dialog.exec_() == QDialog.Accepted:
|
|
self.config = dialog.get_values()
|
|
save_config(self.config)
|
|
|
|
def quit(self):
|
|
if self.overlay:
|
|
self.overlay.close()
|
|
self.app.quit()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app = QApplication(sys.argv)
|
|
app.setQuitOnLastWindowClosed(False)
|
|
|
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
timer = QTimer()
|
|
timer.start(200)
|
|
timer.timeout.connect(lambda: None)
|
|
|
|
tray = TrayApp(app)
|
|
sys.exit(app.exec_())
|