feat: propagate client screen size to web runtime
This commit is contained in:
@@ -8,11 +8,16 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
DISPLAY = os.environ.get("DISPLAY", ":1")
|
||||
CHROME_WINDOW_SIZE = os.environ.get("CHROME_WINDOW_SIZE", "1920,1080")
|
||||
RESOLUTION_MIN_WIDTH = int(os.environ.get("WEB_RESOLUTION_MIN_WIDTH", "1024"))
|
||||
RESOLUTION_MIN_HEIGHT = int(os.environ.get("WEB_RESOLUTION_MIN_HEIGHT", "720"))
|
||||
RESOLUTION_MAX_WIDTH = int(os.environ.get("WEB_RESOLUTION_MAX_WIDTH", "3840"))
|
||||
RESOLUTION_MAX_HEIGHT = int(os.environ.get("WEB_RESOLUTION_MAX_HEIGHT", "2160"))
|
||||
|
||||
_state = {
|
||||
"proc": None,
|
||||
"mode": "idle",
|
||||
"target": "",
|
||||
"resolution": CHROME_WINDOW_SIZE,
|
||||
}
|
||||
_lock = threading.Lock()
|
||||
|
||||
@@ -50,7 +55,37 @@ def _start_process(cmd: list[str], mode: str, target: str) -> None:
|
||||
_state["target"] = target
|
||||
|
||||
|
||||
def open_web(url: str) -> None:
|
||||
def _sanitize_resolution(width: int | None, height: int | None) -> tuple[int, int]:
|
||||
if not width or not height:
|
||||
try:
|
||||
default_w, default_h = [int(x) for x in CHROME_WINDOW_SIZE.split(",", 1)]
|
||||
return default_w, default_h
|
||||
except Exception:
|
||||
return 1920, 1080
|
||||
|
||||
safe_w = max(RESOLUTION_MIN_WIDTH, min(int(width), RESOLUTION_MAX_WIDTH))
|
||||
safe_h = max(RESOLUTION_MIN_HEIGHT, min(int(height), RESOLUTION_MAX_HEIGHT))
|
||||
return safe_w, safe_h
|
||||
|
||||
|
||||
def apply_resolution(width: int | None, height: int | None) -> tuple[int, int]:
|
||||
safe_w, safe_h = _sanitize_resolution(width, height)
|
||||
# Best effort: Xvfb usually exposes RandR and accepts xrandr -s.
|
||||
try:
|
||||
subprocess.run( # noqa: S603
|
||||
["xrandr", "-display", DISPLAY, "-s", f"{safe_w}x{safe_h}"],
|
||||
check=False,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
_state["resolution"] = f"{safe_w},{safe_h}"
|
||||
return safe_w, safe_h
|
||||
|
||||
|
||||
def open_web(url: str, width: int | None = None, height: int | None = None) -> None:
|
||||
safe_w, safe_h = apply_resolution(width, height)
|
||||
cmd = [
|
||||
"chromium",
|
||||
"--no-sandbox",
|
||||
@@ -65,7 +100,7 @@ def open_web(url: str) -> None:
|
||||
"--ignore-certificate-errors",
|
||||
"--allow-insecure-localhost",
|
||||
"--allow-running-insecure-content",
|
||||
f"--window-size={CHROME_WINDOW_SIZE}",
|
||||
f"--window-size={safe_w},{safe_h}",
|
||||
"--no-first-run",
|
||||
"--no-default-browser-check",
|
||||
url,
|
||||
@@ -125,7 +160,16 @@ class Handler(BaseHTTPRequestHandler):
|
||||
if self.path == "/health":
|
||||
proc = _state.get("proc")
|
||||
running = bool(proc and proc.poll() is None)
|
||||
self._json(200, {"ok": True, "mode": _state.get("mode", "idle"), "running": running, "target": _state.get("target", "")})
|
||||
self._json(
|
||||
200,
|
||||
{
|
||||
"ok": True,
|
||||
"mode": _state.get("mode", "idle"),
|
||||
"running": running,
|
||||
"target": _state.get("target", ""),
|
||||
"resolution": _state.get("resolution", CHROME_WINDOW_SIZE),
|
||||
},
|
||||
)
|
||||
return
|
||||
self._json(404, {"detail": "Not found"})
|
||||
|
||||
@@ -137,9 +181,26 @@ class Handler(BaseHTTPRequestHandler):
|
||||
if not (url.startswith("http://") or url.startswith("https://")):
|
||||
self._json(400, {"detail": "Invalid URL"})
|
||||
return
|
||||
width = data.get("width")
|
||||
height = data.get("height")
|
||||
with _lock:
|
||||
open_web(url)
|
||||
self._json(200, {"ok": True, "mode": "web", "target": url})
|
||||
open_web(url, width=width, height=height)
|
||||
self._json(
|
||||
200,
|
||||
{
|
||||
"ok": True,
|
||||
"mode": "web",
|
||||
"target": url,
|
||||
"resolution": _state.get("resolution", CHROME_WINDOW_SIZE),
|
||||
},
|
||||
)
|
||||
return
|
||||
if self.path == "/resolution":
|
||||
width = data.get("width")
|
||||
height = data.get("height")
|
||||
with _lock:
|
||||
safe_w, safe_h = apply_resolution(width, height)
|
||||
self._json(200, {"ok": True, "width": safe_w, "height": safe_h})
|
||||
return
|
||||
if self.path == "/rdp":
|
||||
with _lock:
|
||||
|
||||
Reference in New Issue
Block a user