Files
kefu/wechat_rpa/tmp/stress_webengine_paint.py
T
2026-08-19 17:35:59 +08:00

136 lines
4.4 KiB
Python

# -*- coding: utf-8 -*-
"""Visible Windows/QWebEngine paint stress probe for the scaled console shell."""
import os
import sys
from pathlib import Path
os.environ.setdefault("QT_SCALE_FACTOR", "1")
os.environ.setdefault("QTWEBENGINE_CHROMIUM_FLAGS", "--enable-logging=stderr --v=0")
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
sys.argv = [sys.argv[0], "--qt-smoke-test", "--qt-paint-stress-test"]
from PySide6.QtCore import QPoint, QSize, Qt, QTimer
from PySide6.QtTest import QTest
from PySide6.QtWidgets import QApplication
from wechat_gui_qt import (
APP_QSS,
CONSOLE_VIEWS,
MainWindow,
WIN_TITLE,
_app_icon,
_register_bundled_fonts,
_ui_font,
)
def dark_samples(image, shell, source_box, step=5):
source_x1, source_y1, source_x2, source_y2 = source_box
scale = min(shell.width() / 1630.0, shell.height() / 920.0)
dpr_x = image.width() / max(1.0, float(shell.width()))
dpr_y = image.height() / max(1.0, float(shell.height()))
count = 0
for source_x in range(source_x1, source_x2, step):
for source_y in range(source_y1, source_y2, step):
x = min(image.width() - 1, max(0, round(source_x * scale * dpr_x)))
y = min(image.height() - 1, max(0, round(source_y * scale * dpr_y)))
colour = image.pixelColor(x, y)
if max(colour.red(), colour.green(), colour.blue()) < 180:
count += 1
return count
app = QApplication.instance() or QApplication(sys.argv)
_register_bundled_fonts()
app.setApplicationName(WIN_TITLE)
app.setWindowIcon(_app_icon())
app.setStyle("Fusion")
app.setStyleSheet(APP_QSS)
app.setFont(_ui_font(9))
window = MainWindow()
window.setFixedSize(QSize(1506, 909))
window.show()
window.raise_()
state = {
"frame": 0,
"bad": 0,
"rail_min": 10**9,
"main_min": 10**9,
}
out_dir = ROOT / "tmp" / "paint-stress"
out_dir.mkdir(exist_ok=True)
frame_limit = max(1, int(os.environ.get("PAINT_STRESS_FRAMES", "210")))
toggle_surface = os.environ.get("PAINT_STRESS_TOGGLE_SURFACE", "0") == "1"
def probe_frame():
index = state["frame"] % len(CONSOLE_VIEWS)
if toggle_surface and state["frame"] and state["frame"] % 7 == 0:
window.console_shell.hide()
QApplication.processEvents()
window.console_shell.show()
window.show_page(index)
window._push_console_state(force=True)
scale = min(window.console_shell.width() / 1630.0, window.console_shell.height() / 920.0)
nav_y = (145, 222, 297, 372, 450, 528, 861)[index]
QTest.mouseMove(
window.console_shell,
QPoint(round(60 * scale), round(nav_y * scale)),
delay=1,
)
QTimer.singleShot(90, capture_frame)
def capture_frame():
index = state["frame"] % len(CONSOLE_VIEWS)
view = CONSOLE_VIEWS[index]
pixmap = window.screen().grabWindow(int(window.winId()))
image = pixmap.toImage()
rail = dark_samples(image, window.console_shell, (20, 20, 145, 900), 5)
main = dark_samples(image, window.console_shell, (175, 205, 1600, 875), 7)
state["rail_min"] = min(state["rail_min"], rail)
state["main_min"] = min(state["main_min"], main)
# Healthy frames are far above these deliberately conservative floors.
if rail < 60 or main < 2000:
state["bad"] += 1
path = out_dir / f"bad-{state['frame']:03d}-{view}-r{rail}-m{main}.png"
pixmap.save(str(path))
print("BAD", state["frame"], view, rail, main, path, flush=True)
state["frame"] += 1
if state["frame"] >= frame_limit:
print(
"RESULT",
f"frames={state['frame']}",
f"bad={state['bad']}",
f"rail_min={state['rail_min']}",
f"main_min={state['main_min']}",
f"size={image.width()}x{image.height()}",
f"shell={window.console_shell.width()}x{window.console_shell.height()}",
flush=True,
)
app.exit(0 if state["bad"] == 0 else 3)
return
if state["frame"] % 20 == 0:
print("FRAME", state["frame"], view, rail, main, flush=True)
QTimer.singleShot(35, probe_frame)
def wait_ready():
if window.console_shell.page_ready and window.console_shell.channel_ready:
QTimer.singleShot(700, probe_frame)
return
QTimer.singleShot(100, wait_ready)
QTimer.singleShot(100, wait_ready)
QTimer.singleShot(max(30_000, frame_limit * 400), lambda: app.exit(4))
raise SystemExit(app.exec())